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

带泛型密封层级的Kotlin多态序列化报错问题排查

密封泛型数据类多态序列化报错的根因与解决方法

问题根因

你遇到的异常源于泛型类型擦除:虽然Coded和NumberedData均为带@Serializable的密封接口,但当CodedData<C>作为NumberedData的实现进行多态序列化时,编译期泛型类型信息会被擦除,序列化框架无法自动关联C对应的Coded密封子类。密封层级的自动注册仅在直接处理该密封类型时生效,泛型上下文会打断这种自动关联逻辑,导致框架判定CodeOB未在Coded的作用域内注册。

解决方案

方案1:显式注册Coded的多态序列化器

创建Json实例时,通过SerializersModule明确注册Coded的所有子类,让框架知晓该密封层级的实现类:

internal class GenericSerializerTest {
    @Test
    fun `polymorphically serialize and deserialize a CodedData instance`() {
        val json = Json {
            serializersModule = SerializersModule {
                polymorphic(Coded::class) {
                    subclass(CodeOA::class)
                    subclass(CodeOB::class)
                }
            }
        }
        
        val codedData: NumberedData = CodedData(
            number = 42,
            info = "Some test",
            code = CodeOB
        )
        val codedDataJson = json.encodeToString(codedData)
        val codedDataDeserialized = json.decodeFromString<NumberedData>(codedDataJson)
        assertEquals(codedData, codedDataDeserialized)
    }
}

方案2:为code字段添加@Polymorphic注解

在CodedData的code字段上标记@Polymorphic,强制框架对该字段进行多态序列化,绕过泛型类型擦除的限制:

@Serializable
@SerialName("CodedData")
data class CodedData<out C : Coded> (
    override val number: Int,
    val info: String,
    @Polymorphic val code: C
): NumberedData

此方案无需修改Json配置,通过注解直接明确字段的多态序列化需求,适合局部场景使用。

验证说明

两种方案的核心都是弥补泛型类型擦除导致的信息缺失,让序列化框架获取到Coded密封层级的子类信息,从而完成正常的序列化与反序列化流程。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 20:02:50