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

Kotlin密封类多态反序列化属性值为空问题求助

解决Kotlin密封类反序列化属性为Null的问题

问题根源

  1. 基类Event的属性是默认值为null的普通属性,未标记为可序列化的抽象属性,子类也未覆盖或声明对应可序列化字段,导致JSON数据无法映射到实例属性。
  2. 自定义序列化器仅负责选择子类序列化器,但子类本身无接收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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 13:05:19