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

如何用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 04:50:14