Kotlin密封类多态反序列化属性值为空问题求助
解决Kotlin密封类反序列化属性为Null的问题
问题根源
- 基类
Event的属性是默认值为null的普通属性,未标记为可序列化的抽象属性,子类也未覆盖或声明对应可序列化字段,导致JSON数据无法映射到实例属性。 - 自定义序列化器仅负责选择子类序列化器,但子类本身无接收JSON字段的属性,最终只能使用基类的默认null值。
修正方案
1. 重构基类与子类
将基类属性改为抽象属性,子类使用data class实现并继承这些属性,同时添加子类独有的字段:
@ExperimentalSerializationApi @Serializable(with = EventSerializer::class) sealed class Event { abstract val eventName: String abstract val productName: String } @Serializable data class EventSuccess( override val eventName: String, override val productName: String ) : Event() @Serializable data class EventFailure( override val eventName: String, override val productName: String, val error: String ) : Event() @Serializable data class EventInvalid( override val eventName: String? = null, override val productName: String? = null ) : Event()
2. 调整序列化器(确保枚举匹配)
保留原序列化器逻辑,需保证EventType枚举值与JSON中的eventName完全一致:
@ExperimentalSerializationApi @Serializer(forClass = Event::class) object EventSerializer : JsonContentPolymorphicSerializer<Event>(Event::class) { override fun selectDeserializer(element: JsonElement): DeserializationStrategy<out Event> { return element.jsonObject["eventName"]?.jsonPrimitive?.content?.let { eventName -> when (EventType.valueOf(eventName)) { EventType.FAILURE -> EventFailure.serializer() EventType.SUCCESS -> EventSuccess.serializer() } } ?: EventInvalid.serializer() } } // 枚举值需与JSON中的eventName严格匹配 enum class EventType { SUCCESS, FAILURE }
3. 验证反序列化效果
执行反序列化代码后,属性值将被正确填充:
val jsonList = """ [ {"eventName": "SUCCESS", "productName": "BLAH"}, {"eventName": "FAILURE", "productName": "BLAH", "error": "Something went wrong"} ] """ val events = Json.decodeFromString<Array<Event>>(jsonList) events.forEach { println(it) println(it.productName) }
输出结果:
EventSuccess(eventName=SUCCESS, productName=BLAH) BLAH EventFailure(eventName=FAILURE, productName=BLAH, error=Something went wrong) BLAH
原理说明
- 基类抽象属性强制子类实现,确保每个子类都有对应字段接收JSON数据。
data class自动生成序列化所需组件,配合@Serializable注解,让Kotlinx Serialization能正确映射JSON字段到类属性。- 自定义序列化器仅负责根据
eventName选择子类序列化器,属性填充由子类自身的序列化逻辑完成。
内容的提问来源于stack exchange,提问作者Jan Vladimir Mostert
相关产品推荐
相关产品推荐

