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

使用kotlinx.serialization解析Kotlin中多类型字段(字符串/对象)

用kotlinx.serialization解析多类型字段(String/自定义Object)

要处理同一个字段既可能是String又可能是自定义Object的情况,最直接的方案是用密封类+自定义序列化器实现类型适配,具体步骤如下:

1. 定义密封类统一字段类型

先创建一个密封类,用来包裹两种可能的取值类型:

@Serializable(with = SomethingFieldSerializer::class)
sealed class SomethingField {
    // 对应String类型的情况
    data class StringValue(val value: String) : SomethingField()
    // 对应自定义Object的情况
    data class ObjectValue(val data: SomethingObject) : SomethingField()
}

@Serializable
data class SomethingObject(
    val list1: List<Int>,
    val list2: List<Int>,
)

2. 实现自定义序列化器

编写自定义序列化器,判断JSON元素的类型后分别解析成对应的密封类实例:

object SomethingFieldSerializer : KSerializer<SomethingField> {
    override val descriptor: SerialDescriptor =
        buildClassSerialDescriptor("SomethingField")

    override fun deserialize(decoder: Decoder): SomethingField {
        val jsonElement = decoder.decodeJsonElement()
        return when (jsonElement) {
            // 解析String类型
            is JsonPrimitive -> {
                require(jsonElement.isString) { "Expected String type for somethingField" }
                SomethingField.StringValue(jsonElement.content)
            }
            // 解析自定义Object类型
            is JsonObject -> {
                val objectData = decoder.json.decodeFromJsonElement<SomethingObject>(jsonElement)
                SomethingField.ObjectValue(objectData)
            }
            else -> throw SerializationException("Unsupported type for somethingField")
        }
    }

    override fun serialize(encoder: Encoder, value: SomethingField) {
        // 如需序列化回后端,处理反向逻辑
        when (value) {
            is SomethingField.StringValue -> encoder.encodeString(value.value)
            is SomethingField.ObjectValue -> encoder.encodeSerializableValue(SomethingObject.serializer(), value.data)
        }
    }
}

3. 修改目标数据类

将原SomeObject中的somethingField类型替换为密封类SomethingField:

@Serializable
data class SomeObject(
    // 其他字段...
    val somethingField: SomethingField
)

使用示例

解析后可通过when表达式安全处理两种情况:

val someObject = Json.decodeFromString<SomeObject>(jsonString)
when (someObject.somethingField) {
    is SomethingField.StringValue -> {
        val strValue = (someObject.somethingField as SomethingField.StringValue).value
        // 处理字符串逻辑
    }
    is SomethingField.ObjectValue -> {
        val objectData = (someObject.somethingField as SomethingField.ObjectValue).data
        // 处理对象逻辑
    }
}

这种方案的优势是类型安全,编译期就能覆盖所有可能的取值情况,避免运行时类型转换错误。

内容的提问来源于stack exchange,提问作者Сергей Беляков

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 22:12:20