如何使用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
相关产品推荐
相关产品推荐

