带泛型密封层级的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
相关产品推荐
相关产品推荐

