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

kotlinx.serialization中Jackson@JsonUnwrapped的等效实现方法

Kotlin序列化实现Map属性的“解包”(类似Jackson的@JsonUnwrapped)

Kotlin序列化没有提供像Jackson的@JsonUnwrapped那样的现成注解,但可以通过自定义序列化器实现把Map的键值对提升到对象顶层的需求。

实现步骤

  1. 自定义序列化器:编写Example类的序列化器,先序列化固定属性id,再将items中的键值对直接写入顶层;反序列化时则把除id外的所有顶层键值对收集到items中。
  2. 给数据类指定序列化器:在@Serializable注解中绑定自定义的序列化器。

完整代码示例

自定义序列化器

import kotlinx.serialization.KSerializer
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.descriptors.buildClassSerialDescriptor
import kotlinx.serialization.encoding.*

object ExampleSerializer : KSerializer<Example> {
    override val descriptor: SerialDescriptor = buildClassSerialDescriptor("Example") {
        element<Int>("id")
    }

    override fun serialize(encoder: Encoder, value: Example) {
        encoder.encodeStructure(descriptor) {
            // 先序列化id属性
            encodeIntElement(descriptor, 0, value.id)
            // 将items的键值对直接写入顶层
            value.items.forEach { (key, intValue) ->
                encodeInt(key, intValue)
            }
        }
    }

    override fun deserialize(decoder: Decoder): Example {
        val items = mutableMapOf<String, Int>()
        var id = 0

        decoder.decodeStructure(descriptor) {
            while (true) {
                when (val index = decodeElementIndex(descriptor)) {
                    CompositeDecoder.DECODE_DONE -> break
                    0 -> id = decodeIntElement(descriptor, index)
                    else -> {
                        val key = descriptor.getElementName(index)
                        items[key] = decodeIntElement(descriptor, index)
                    }
                }
            }
        }

        return Example(id, items)
    }
}

修改数据类并测试

import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json

@Serializable(with = ExampleSerializer::class)
data class Example(
    val id: Int,
    val items: Map<String, Int>
)

fun main() {
    val instance = Example(1, hashMapOf("one" to 1, "two" to 2))
    val json = Json.encodeToString(instance)
    println(json) // 输出: {"id":1,"one":1,"two":2}
}

注意事项

  • 如果items的值是其他类型(如String、Boolean),需要对应修改序列化器中的encodeXxx和decodeXxx方法;若要支持任意类型,可以使用更通用的序列化逻辑。
  • 反序列化逻辑会自动把所有非id的顶层键值对收集到items中,确保双向序列化的一致性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 16:37:33