如何用kotlinx将指定JSON反序列化为带序列化名的POJO?
解决方案:自定义序列化器实现原始值到Slot的转换
你的需求是将JSON中的原始值字段直接反序列化为包含字段名(序列化名称)和对应值的Slot对象,核心问题是默认序列化逻辑期望JSON字段结构与Slot类匹配,但实际输入是原始值,因此需要自定义序列化器完成转换。
步骤1:修正基础类定义
先修正Slot和Slots的类型(Kotlin中使用Int而非Integer):
@Serializable class Slot<T>(val name: String, val value: T) @Serializable class Slots( @SerialName("a") val propertyA: Slot<Int>? = null, @SerialName("b") val propertyB: Slot<String>? = null, @SerialName("c") val propertyC: Slot<Boolean>? = null )
步骤2:编写通用Slot序列化器
创建抽象通用序列化器,接收目标字段名和值类型序列化器,实现原始值与Slot对象的双向转换:
abstract class SlotSerializer<T>( private val fieldName: String, private val valueSerializer: KSerializer<T> ) : KSerializer<Slot<T>> { // 描述符与原始值类型保持一致,确保序列化/反序列化兼容原始JSON结构 override val descriptor: SerialDescriptor = valueSerializer.descriptor // 序列化时,只输出Slot的value值(还原为原始JSON结构) override fun serialize(encoder: Encoder, value: Slot<T>) { valueSerializer.serialize(encoder, value.value) } // 反序列化时,读取原始值并包装为Slot,自动填充字段名 override fun deserialize(decoder: Decoder): Slot<T> { val rawValue = valueSerializer.deserialize(decoder) return Slot(fieldName, rawValue) } }
步骤3:为每个字段创建专属序列化器
针对Slots中的每个属性,创建对应字段名的具体序列化器:
// 对应"a"字段,值类型为Int class SlotASerializer : SlotSerializer<Int>("a", Int.serializer()) // 对应"b"字段,值类型为String class SlotBSerializer : SlotSerializer<String>("b", String.serializer()) // 对应"c"字段,值类型为Boolean class SlotCSerializer : SlotSerializer<Boolean>("c", Boolean.serializer())
步骤4:为Slots属性指定序列化器
在Slots类的每个属性上添加@Serializable(with = ...)注解,绑定对应的专属序列化器:
@Serializable class Slots( @SerialName("a") @Serializable(with = SlotASerializer::class) val propertyA: Slot<Int>? = null, @SerialName("b") @Serializable(with = SlotBSerializer::class) val propertyB: Slot<String>? = null, @SerialName("c") @Serializable(with = SlotCSerializer::class) val propertyC: Slot<Boolean>? = null )
测试验证
使用Json.decodeFromString进行反序列化测试:
fun main() { val json = """{"a": 123, "b": "foo", "c": false}""" val result = Json.decodeFromString<Slots>(json) println(result) // 输出:Slots(propertyA=Slot(name=a, value=123), propertyB=Slot(name=b, value=foo), propertyC=Slot(name=c, value=false)) }
该方案既能完成反序列化时的包装,也能保证序列化时将Slot对象还原为原始JSON字段结构,满足双向兼容需求。
内容的提问来源于stack exchange,提问作者Bakkenrak
相关产品推荐
相关产品推荐

