kotlinx.serialization反序列化泛型类提示星投影不允许报错如何解决
适配方案
核心思路:保留原有Message类的默认序列化能力不修改,单独实现仅用于星投影场景的自定义序列化器,复用kotlinx.serialization对密封接口的原生多态反序列化能力,无硬编码逻辑。
1. 保留原有类定义不变
不要给Message类加全局@Serializable(with = ...)注解,避免影响原有带具体泛型的序列化/反序列化逻辑,基础类定义示例:
// 内层业务数据密封接口,自带多态鉴别器 @JsonClassDiscriminator("info_type") @Serializable sealed interface SpecificInformation // 业务子类示例,新增子类无需修改其他逻辑 @Serializable data class CarInfo(val brand: String, val price: Int) : SpecificInformation @Serializable data class UserInfo(val name: String, val age: Int) : SpecificInformation // 外层消息类,使用默认序列化生成逻辑 @Serializable data class Message<out DataType : SpecificInformation>( val msgId: String, val timestamp: Long, val data: DataType )
2. 实现星投影专用自定义序列化器
直接复用插件生成的Message序列化器和SpecificInformation的多态序列化器,无需手动解析JSON或硬编码鉴别器:
import kotlinx.serialization.KSerializer import kotlinx.serialization.descriptors.SerialDescriptor import kotlinx.serialization.encoding.Decoder import kotlinx.serialization.encoding.Encoder object MessageStarProjectionSerializer : KSerializer<Message<*>> { // 复用密封接口原生多态序列化能力 private val dataSerializer = SpecificInformation.serializer() // 复用插件生成的Message序列化逻辑,避免手动解析 private val delegateSerializer = Message.serializer(dataSerializer) override val descriptor: SerialDescriptor = delegateSerializer.descriptor override fun serialize(encoder: Encoder, value: Message<*>) { // 序列化场景按需实现,不需要可直接抛出异常 delegateSerializer.serialize(encoder, value as Message<SpecificInformation>) } override fun deserialize(decoder: Decoder): Message<*> { return delegateSerializer.deserialize(decoder) } }
3. 调用方式
两种调用方式可选:
- 显式传入序列化器调用(无侵入):
val msg = Json.decodeFromString(MessageStarProjectionSerializer, carJson) - 文件级全局生效:在需要使用
Message<*>反序列化的文件头部添加注解,即可直接使用目标语法:@file:UseSerializers(MessageStarProjectionSerializer::class) // 后续可直接调用 val msg = Json.decodeFromString<Message<*>>(carJson)
方案优势
- 完全满足约束:无需修改JSON结构、无需移动鉴别器位置、无需自定义
SerializersModule - 无硬编码逻辑:新增
SpecificInformation子类无需修改序列化器代码,自动适配密封接口的多态特性 - 不影响原有逻辑:原有带具体泛型的
Message.serializer(subclassSerializer)调用完全正常,无无限循环问题 - 反序列化后可直接通过
when判断data字段的实际类型,符合业务处理需求
内容的提问来源于stack exchange,提问作者aSemy
相关产品推荐
相关产品推荐

