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

如何用Kotlinx.Serialization处理JSON多态字段(String/Int)反序列化?

问题原因

你写的序列化器错误调用了beginStructure()解析数据——这个方法是用来处理JSON对象/数组这类结构化数据的,但API返回的reserved_stock是单个原始值(Int或String),所以解码器会抛出“期望对象却找到Int(或String)”的异常。

正确处理方案

直接针对原始值类型做判断,不需要开启结构解析,以下是修正后的代码:

import kotlinx.serialization.*
import kotlinx.serialization.json.JsonDecoder
import kotlinx.serialization.json.JsonPrimitive

@Serializable(with = ReservedStockSerializer::class)
sealed class ReservedStock {
    data class IntValue(val value: Int) : ReservedStock()
    data class StringValue(val value: String) : ReservedStock()
}

object ReservedStockSerializer : KSerializer<ReservedStock> {
    override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("ReservedStock", PrimitiveKind.STRING)

    override fun serialize(encoder: Encoder, value: ReservedStock) {
        when (value) {
            is ReservedStock.IntValue -> encoder.encodeInt(value.value)
            is ReservedStock.StringValue -> encoder.encodeString(value.value)
        }
    }

    override fun deserialize(decoder: Decoder): ReservedStock {
        return if (decoder is JsonDecoder) {
            // 针对JSON格式直接解析原始元素类型
            val jsonElement = decoder.decodeJsonElement()
            when (jsonElement) {
                is JsonPrimitive -> {
                    if (jsonElement.isInt) {
                        ReservedStock.IntValue(jsonElement.int)
                    } else {
                        ReservedStock.StringValue(jsonElement.content)
                    }
                }
                else -> throw SerializationException("ReservedStock 必须是Int或String类型的原始值")
            }
        } else {
            // 适配非JSON解码器,先尝试解析Int,失败则解析String
            try {
                ReservedStock.IntValue(decoder.decodeInt())
            } catch (e: SerializationException) {
                ReservedStock.StringValue(decoder.decodeString())
            }
        }
    }
}
代码说明
  1. 移除结构解析逻辑:不再调用beginStructure(),直接处理原始值
  2. JSON格式优化处理:通过JsonDecoder直接获取JsonElement,判断是Int类型的原始值还是String类型
  3. 兼容非JSON场景:针对非JSON解码器(比如Protobuf等),用try-catch的方式先尝试解析Int,失败则解析String
  4. 序列化逻辑对齐:序列化时根据类型直接输出Int或String,保持和API返回格式一致

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 01:28:14