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

Kotlin泛型嵌套多态序列化:如何注册Pair为多态子类?

问题:序列化Map<String, Any>中的Pair<Int, Int>,注册多态子类失败

错误信息(中文翻译)

主线程异常:java.lang.ExceptionInInitializerError
引起原因:java.lang.IllegalArgumentException: Pair的序列化器无法注册为多态序列化的子类,因为它的类型为OPEN(未绑定具体泛型参数),并非具体类型。若要处理多继承结构,请将其注册为基类。
at kotlinx.serialization.json.internal.PolymorphismValidator.checkKind(PolymorphismValidator.kt:41)
at kotlinx.serialization.json.internal.PolymorphismValidator.polymorphic(PolymorphismValidator.kt:31)
at kotlinx.serialization.modules.SerialModuleImpl.dumpTo(SerializersModule.kt:189)
at kotlinx.serialization.json.JsonImpl.validateConfiguration(Json.kt:358)
at kotlinx.serialization.json.JsonImpl.(Json.kt:352)
at kotlinx.serialization.json.JsonKt.Json(Json.kt:189)
at kotlinx.serialization.json.JsonKt.Json$default(Json.kt:185)
at MainKt.(Main.kt:143)

错误原因

Pair::class是泛型类,对应的序列化器属于OPEN类型(未绑定具体泛型参数),而kotlinx.serialization要求多态子类必须是CONCRETE具体类型(绑定明确泛型参数或非泛型类),因此直接将Pair::class注册为Any的多态子类会触发该错误。

解决方案

需要为具体的Pair<Int, Int>实现序列化器,再将Pair注册为多态基类,最后把Pair::class作为Any的多态子类注册。

完整实现代码

import kotlinx.serialization.*
import kotlinx.serialization.descriptors.*
import kotlinx.serialization.encoding.*
import kotlinx.serialization.json.*
import kotlinx.serialization.modules.*

// 为Pair<Int, Int>实现自定义序列化器
val pairIntIntSerializer = object : KSerializer<Pair<Int, Int>> {
    override val descriptor: SerialDescriptor = buildClassSerialDescriptor("Pair") {
        element("first", Int.serializer().descriptor)
        element("second", Int.serializer().descriptor)
    }

    override fun serialize(encoder: Encoder, value: Pair<Int, Int>) {
        encoder.encodeStructure(descriptor) {
            encodeSerializableElement(descriptor, 0, Int.serializer(), value.first)
            encodeSerializableElement(descriptor, 1, Int.serializer(), value.second)
        }
    }

    override fun deserialize(decoder: Decoder): Pair<Int, Int> {
        return decoder.decodeStructure(descriptor) {
            var first = 0
            var second = 0
            while (true) {
                when (val index = decodeElementIndex(descriptor)) {
                    0 -> first = decodeSerializableElement(descriptor, 0, Int.serializer())
                    1 -> second = decodeSerializableElement(descriptor, 1, Int.serializer())
                    CompositeDecoder.DECODE_DONE -> break
                    else -> error("Unexpected index $index")
                }
            }
            first to second
        }
    }
}

fun main() {
    val module = SerializersModule {
        // 注册Pair作为多态基类,绑定Pair<Int, Int>的序列化器
        polymorphic(Pair::class) {
            @Suppress("UNCHECKED_CAST")
            subclass(Pair::class as KClass<Pair<Int, Int>>, pairIntIntSerializer)
        }
        // 注册Any的多态子类,包含Int、String和Pair
        polymorphic(Any::class) {
            subclass(Int::class, PolymorphicPrimitiveSerializer(Int.serializer()))
            subclass(String::class, PolymorphicPrimitiveSerializer(String.serializer()))
            subclass(Pair::class, PolymorphicSerializer(Pair::class))
        }
    }

    val format = Json {
        serializersModule = module
        prettyPrint = true
    }

    val mm = mapOf<String, Any>(
        "int-int pair" to (5 to 10),
        "test int" to 100,
        "test string" to "hello"
    )

    val jsoned = format.encodeToString(mm)
    println(jsoned)

    val mmDecoded = format.decodeFromString<Map<String, Any>>(jsoned)
    require(mm == mmDecoded)
}

代码说明

  1. 自定义序列化器:pairIntIntSerializer专门处理Pair<Int, Int>的序列化/反序列化,符合kotlinx.serialization的规范。
  2. 多态基类注册:将Pair作为多态基类,绑定具体的Pair<Int, Int>序列化器(通过@Suppress消除泛型类型转换的警告)。
  3. Any的多态子类注册:将Pair::class注册为Any的多态子类,使用PolymorphicSerializer处理多态标识(生成带type和value的JSON结构)。
  4. JSON格式化:开启prettyPrint可以输出格式化后的JSON,与期望格式一致。

输出示例

{
    "int-int pair": {
        "type": "Pair",
        "value": {
            "first": 5,
            "second": 10
        }
    },
    "test int": {
        "type": "Int",
        "value": 100
    },
    "test string": {
        "type": "String",
        "value": "hello"
    }
}

内容的提问来源于stack exchange,提问作者A-_-S

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 06:45:53