如何用kotlinx serialization将多JSON字段反序列化为单个对象
如何将JSON中的latitude/longitude字段反序列化为嵌套的Location对象
问题背景
现有如下JSON结构表示基础签到信息:
{ "id": "53481198005", "date": "1995-01-01 00:00:00", "latitude": "50.765391", "longitude": "60.765391" }
需要将JSON中的latitude和longitude字段整合为嵌套的Location对象,使用如下Kotlin数据类完成反序列化:
@Serializable data class CheckInRecord(val id: String, val date: String, val location: Location) @Serializable data class Location(val latitude: String, val longitude: String)
解决方案(基于kotlinx.serialization)
方法1:自定义反序列化器
为CheckInRecord编写自定义反序列化逻辑,手动从JSON中提取字段并构建Location对象:
import kotlinx.serialization.* import kotlinx.serialization.descriptors.* import kotlinx.serialization.encoding.* import kotlinx.serialization.json.* // 指定使用自定义序列化器 @Serializable(with = CheckInRecordSerializer::class) data class CheckInRecord(val id: String, val date: String, val location: Location) @Serializable data class Location(val latitude: String, val longitude: String) // 实现自定义反序列化器 object CheckInRecordSerializer : DeserializationStrategy<CheckInRecord> { override val descriptor: SerialDescriptor = buildClassSerialDescriptor("CheckInRecord") { element<String>("id") element<String>("date") element<String>("latitude") element<String>("longitude") } override fun deserialize(decoder: Decoder): CheckInRecord { val jsonObj = (decoder as JsonDecoder).decodeJsonElement().jsonObject // 从JSON对象中提取字段 val id = jsonObj["id"]?.jsonPrimitive?.content ?: error("缺失id字段") val date = jsonObj["date"]?.jsonPrimitive?.content ?: error("缺失date字段") val latitude = jsonObj["latitude"]?.jsonPrimitive?.content ?: error("缺失latitude字段") val longitude = jsonObj["longitude"]?.jsonPrimitive?.content ?: error("缺失longitude字段") return CheckInRecord(id, date, Location(latitude, longitude)) } }
使用示例
fun main() { val json = """ { "id": "53481198005", "date": "1995-01-01 00:00:00", "latitude": "50.765391", "longitude": "60.765391" } """.trimIndent() val record = Json.decodeFromString<CheckInRecord>(json) println(record) // 输出:CheckInRecord(id=53481198005, date=1995-01-01 00:00:00, location=Location(latitude=50.765391, longitude=60.765391)) }
方法2:次级构造函数配合序列化配置(简洁版)
通过为CheckInRecord添加次级构造函数,让序列化器直接将平级的latitude/longitude字段传入,构建Location对象:
import kotlinx.serialization.* import kotlinx.serialization.json.Json @Serializable data class CheckInRecord( val id: String, val date: String, val location: Location ) { // 供反序列化使用的次级构造函数,接收平级的经纬度字段 @Serializable constructor( id: String, date: String, latitude: String, longitude: String ) : this(id, date, Location(latitude, longitude)) } @Serializable data class Location(val latitude: String, val longitude: String)
使用时直接调用反序列化方法即可(kotlinx.serialization 1.3+默认支持次级构造函数序列化):
fun main() { val json = """ { "id": "53481198005", "date": "1995-01-01 00:00:00", "latitude": "50.765391", "longitude": "60.765391" } """.trimIndent() val record = Json.decodeFromString<CheckInRecord>(json) println(record) }
内容的提问来源于stack exchange,提问作者Peanutbutter
相关产品推荐
相关产品推荐

