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

如何使用kotlinx serialization处理Any类型的序列化与反序列化

根据枚举字段动态处理JSON序列化/反序列化的方案

针对你遇到的「JSON中value类型随type枚举值变化」的场景,官方的@Polymorphic注解和泛型确实无法直接适配自定义的type判断逻辑,下面是一套可行的自定义序列化/反序列化实现方案:

1. 完善数据类结构

先补充对应各type的具体数据子类,覆盖所有场景:

@Serializable(with = MyDataSerializer::class)
abstract class MyData(open val type: Int, open val value: Any)

@Serializable
data class StringData(override val type: Int, override val value: String) : MyData(type, value)

@Serializable
data class IntData(override val type: Int, override val value: Int) : MyData(type, value)

@Serializable
data class IntArrayData(override val type: Int, override val value: List<Int>) : MyData(type, value)

2. 实现自定义序列化器

核心是通过自定义KSerializer,在序列化/反序列化时根据type字段动态处理value的类型:

object MyDataSerializer : KSerializer<MyData> {
    override val descriptor: SerialDescriptor = buildClassSerialDescriptor("MyData") {
        element("type", Int.serializer().descriptor)
        element("value", buildSerialDescriptor("Value", SerialKind.CONTEXTUAL))
    }

    // 序列化:根据实际子类类型写入对应格式的value
    override fun serialize(encoder: Encoder, value: MyData) {
        val compositeEncoder = encoder.beginStructure(descriptor)
        compositeEncoder.encodeIntElement(descriptor, 0, value.type)
        when (value) {
            is StringData -> compositeEncoder.encodeStringElement(descriptor, 1, value.value)
            is IntData -> compositeEncoder.encodeIntElement(descriptor, 1, value.value)
            is IntArrayData -> compositeEncoder.encodeSerializableElement(descriptor, 1, ListSerializer(Int.serializer()), value.value)
            else -> throw SerializationException("未知的MyData类型: ${value.type}")
        }
        compositeEncoder.endStructure(descriptor)
    }

    // 反序列化:先解析type,再根据type解析对应类型的value
    override fun deserialize(decoder: Decoder): MyData {
        val compositeDecoder = decoder.beginStructure(descriptor)
        var type: Int? = null
        var value: Any? = null

        loop@ while (true) {
            when (val index = compositeDecoder.decodeElementIndex(descriptor)) {
                0 -> type = compositeDecoder.decodeIntElement(descriptor, 0)
                1 -> {
                    value = when (type) {
                        1 -> compositeDecoder.decodeStringElement(descriptor, 1)
                        2 -> compositeDecoder.decodeIntElement(descriptor, 1)
                        3 -> compositeDecoder.decodeSerializableElement(descriptor, 1, ListSerializer(Int.serializer()))
                        else -> throw SerializationException("不支持的type值: $type")
                    }
                }
                CompositeDecoder.DECODE_DONE -> break@loop
                else -> throw SerializationException("未知的元素索引: $index")
            }
        }
        compositeDecoder.endStructure(descriptor)

        return when (type) {
            1 -> StringData(type, value as String)
            2 -> IntData(type, value as Int)
            3 -> IntArrayData(type, value as List<Int>)
            else -> throw SerializationException("不支持的type值: $type")
        }
    }
}

3. 使用示例

直接通过Json工具类即可完成数组的序列化/反序列化:

// 反序列化示例
val json = """
[
    {
        "type":1,
        "value":"String"
    },
    {
        "type":2,
        "value": 4
    },
    {
        "type":3,
        "value": [2, 4]
    }
]
""".trimIndent()

val myDataList = Json.decodeFromString(ListSerializer(MyDataSerializer), json)
myDataList.forEach {
    println("Type: ${it.type}, Value: ${it.value} (类型: ${it.value.javaClass.simpleName})")
}

// 序列化示例
val serializedJson = Json.encodeToString(ListSerializer(MyDataSerializer), myDataList)
println(serializedJson)

这个方案的核心是完全基于业务中的type枚举规则来控制value的解析逻辑,完美适配你给出的JSON结构和期望的类结构。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 06:25:34