kotlinx.serialization中Jackson@JsonUnwrapped的等效实现方法
Kotlin序列化实现Map属性的“解包”(类似Jackson的@JsonUnwrapped)
Kotlin序列化没有提供像Jackson的@JsonUnwrapped那样的现成注解,但可以通过自定义序列化器实现把Map的键值对提升到对象顶层的需求。
实现步骤
- 自定义序列化器:编写
Example类的序列化器,先序列化固定属性id,再将items中的键值对直接写入顶层;反序列化时则把除id外的所有顶层键值对收集到items中。 - 给数据类指定序列化器:在
@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
相关产品推荐
相关产品推荐

