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

Kotlin中Any类型多态序列化问题:如何处理Object类型value?

处理Kotlin序列化中动态类型Value的对象类型场景

步骤1:定义对应Object类型的序列化数据类

针对API返回的Object类型value(比如示例中的hsv结构),先创建带@Serializable注解的数据类:

@Serializable
data class HsvValue(
    val h: Int,
    val s: Int,
    val v: Int
)

如果还有其他Object类型的value,按同样方式定义对应的序列化数据类即可。

步骤2:扩展序列化器的类型映射表

修改dataTypeSerializers,将每个instance字符串与对应的类型序列化器关联,覆盖基础类型和自定义对象类型:

private val dataTypeSerializers: Map<String, KSerializer<Any>> =
    mapOf(
        // 基础类型映射
        "rgb" to Int.serializer(),
        "bool" to Boolean.serializer(),
        "text" to String.serializer(),
        // 对象类型映射
        "hsv" to HsvValue.serializer()
    ).mapValues { (_, serializer) -> serializer as KSerializer<Any> }

步骤3:优化反序列化逻辑(可选但推荐)

原代码的decodeSequentially分支可能存在先解析value再解析instance的风险,调整为循环解析确保先拿到instance再处理value:

override fun deserialize(decoder: Decoder): StateObject = decoder.decodeStructure(descriptor) {
    var instance: String? = null
    var value: Any? = null

    while (true) {
        when (val index = decodeElementIndex(descriptor)) {
            0 -> instance = decodeStringElement(descriptor, index)
            1 -> {
                val serializer = getValueSerializer(instance ?: throw SerializationException("Instance字段必须先于Value解析"))
                value = decodeSerializableElement(descriptor, index, serializer)
            }
            CompositeDecoder.DECODE_DONE -> break
            else -> error("Unexpected index: $index")
        }
    }

    StateObject(
        instance ?: throw SerializationException("Instance字段缺失"),
        value ?: throw SerializationException("Value字段缺失")
    )
}

完整修改后的代码

@Serializable(with = StateSerializer::class)
data class StateObject(
    val instance: String,
    val value: Any
)

// 对应hsv类型的序列化数据类
@Serializable
data class HsvValue(
    val h: Int,
    val s: Int,
    val v: Int
)

object StateSerializer : KSerializer<StateObject> {
    private val dataTypeSerializers: Map<String, KSerializer<Any>> =
        mapOf(
            "rgb" to Int.serializer(),
            "bool" to Boolean.serializer(),
            "text" to String.serializer(),
            "hsv" to HsvValue.serializer()
        ).mapValues { (_, serializer) -> serializer as KSerializer<Any> }

    private fun getValueSerializer(instance: String): KSerializer<Any> =
        dataTypeSerializers[instance] ?: throw SerializationException("不支持的instance类型: $instance")

    override val descriptor: SerialDescriptor = buildClassSerialDescriptor("StateObject") {
        element("instance", serialDescriptor<String>())
        element("value", buildClassSerialDescriptor("Any"))
    }

    override fun deserialize(decoder: Decoder): StateObject = decoder.decodeStructure(descriptor) {
        var instance: String? = null
        var value: Any? = null

        while (true) {
            when (val index = decodeElementIndex(descriptor)) {
                0 -> instance = decodeStringElement(descriptor, index)
                1 -> {
                    val serializer = getValueSerializer(instance ?: throw SerializationException("Instance字段必须先于Value解析"))
                    value = decodeSerializableElement(descriptor, index, serializer)
                }
                CompositeDecoder.DECODE_DONE -> break
                else -> error("Unexpected index: $index")
            }
        }

        StateObject(
            instance ?: throw SerializationException("Instance字段缺失"),
            value ?: throw SerializationException("Value字段缺失")
        )
    }

    override fun serialize(encoder: Encoder, value: StateObject) {
        encoder.encodeStructure(descriptor) {
            encodeStringElement(descriptor, 0, value.instance)
            val serializer = getValueSerializer(value.instance)
            encodeSerializableElement(descriptor, 1, serializer, value.value)
        }
    }
}

使用示例

反序列化后可通过类型转换获取具体的value类型:

val state: StateObject = // 从API反序列化得到的对象
when (state.instance) {
    "hsv" -> {
        val hsvValue = state.value as HsvValue
        // 处理HSV逻辑
    }
    "rgb" -> {
        val rgbValue = state.value as Int
        // 处理RGB逻辑
    }
    // 其他类型分支
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 05:35:11