You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Moshi的PolymorphicJsonAdapterFactory在withDefaultValue中如何获取类型标签?

原生PolymorphicJsonAdapterFactory提供的withDefaultValue方法本身不支持获取未匹配的类型标签,你可以通过以下两种方式实现需求:

方案1:自定义多态适配器(推荐)

在原有多态适配逻辑外层包一层自定义工厂,提前读取类型标签后再做匹配,匹配失败时直接获取标签做上报和兜底:

步骤1:定义兜底子类和通用字段

// 原有天气基类
sealed class Weather {
    // 存储实际返回的类型标签,方便后续逻辑使用
    var actualTypeLabel: String? = null
}

data class ColdWeather(val temp: Int) : Weather()
data class HotWeather(val temp: Int) : Weather()
// 新增兜底未知天气类型
data class UnknownWeather(val label: String) : Weather()

步骤2:实现自定义适配器工厂

class WeatherPolymorphicFactory : JsonAdapter.Factory {
    // 复用原有多态适配逻辑
    private val delegateFactory = PolymorphicJsonAdapterFactory.of(Weather::class.java, "type")
        .withSubtype(ColdWeather::class.java, "Cold")
        .withSubtype(HotWeather::class.java, "Hot")

    override fun create(type: Type, annotations: MutableSet<out Annotation>, moshi: Moshi): JsonAdapter<*>? {
        if (type != Weather::class.java) return null
        val delegateAdapter = delegateFactory.create(type, annotations, moshi) as JsonAdapter<Weather>

        return object : JsonAdapter<Weather>() {
            override fun fromJson(reader: JsonReader): Weather? {
                // 先读取完整Json节点,提取类型标签
                val jsonNode = reader.readJsonValue() as? Map<String, Any?> ?: return null
                val typeLabel = jsonNode["type"] as? String
                val parseResult = delegateAdapter.fromJsonValue(jsonNode)

                return if (parseResult == null) {
                    // 未匹配到类型,此处可直接执行上报逻辑
                    Log.e("API_ERROR", "未匹配的天气类型标签:$typeLabel")
                    UnknownWeather(typeLabel.orEmpty())
                } else {
                    parseResult.actualTypeLabel = typeLabel
                    parseResult
                }
            }

            override fun toJson(writer: JsonWriter, value: Weather?) {
                delegateAdapter.toJson(writer, value)
            }
        }
    }
}

步骤3:替换原有配置

把你之前注册PolymorphicJsonAdapterFactory的逻辑,替换为注册上述自定义工厂即可。

方案2:轻量实现(无需自定义适配器)

如果不想改动适配逻辑,也可以直接在基类中声明类型标签字段,让Moshi正常反序列化该字段:

sealed class Weather {
    // 让Moshi直接反序列化type字段到该属性
    val type: String? = null
}

后续拿到反序列化结果后,判断如果是你通过withDefaultValue设置的兜底实例,直接读取type属性的值就能拿到未匹配的标签,再做上报即可。

内容的提问来源于stack exchange,提问作者c_idle

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.09 11:18:00