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

求助:将含不规则坐标的API响应转为Kotlin Data Class

解决方案:自定义JSON反序列化处理动态无序坐标字段

1. 重构数据类结构

先替换原空的MapCoordinate,改成包含有序坐标列表的结构,同时定义单个坐标的实体类:

// 单个坐标点的实体类
data class SingleCoordinate(
    val x: String,
    val y: String,
    val lat: String,
    val lng: String
)

// 替换原空MapCoordinate,存储排序后的坐标列表
data class MapCoordinate(
    val coordinates: List<SingleCoordinate>
)

2. 自定义Gson反序列化器(Android常用方案)

针对后端返回的xN/yN/latN/lngN动态无序字段,手动提取数字后缀、分组排序后组装成有序列表:

class MapCoordinateDeserializer : JsonDeserializer<MapCoordinate> {
    override fun deserialize(
        json: JsonElement,
        typeOfT: Type?,
        context: JsonDeserializationContext?
    ): MapCoordinate {
        val jsonObject = json.asJsonObject
        // 按数字后缀分组存储每个坐标的四个属性
        val coordinateGroups = mutableMapOf<Int, MutableMap<String, String>>()

        jsonObject.entrySet().forEach { entry ->
            val key = entry.key
            val value = entry.value.asString
            // 匹配字段名的前缀(x/y/lat/lng)和数字后缀
            val matchResult = Regex("([a-z]+)(\\d+)").find(key)
            matchResult?.let {
                val prefix = it.groupValues[1]
                val index = it.groupValues[2].toInt()
                // 初始化当前索引的分组容器
                if (!coordinateGroups.containsKey(index)) {
                    coordinateGroups[index] = mutableMapOf()
                }
                coordinateGroups[index]?.put(prefix, value)
            }
        }

        // 按数字索引排序,组装成完整坐标列表
        val sortedCoordinates = coordinateGroups.keys.sorted().mapNotNull { index ->
            val group = coordinateGroups[index]
            // 确保四个属性齐全再组装,避免缺失字段导致异常
            if (group?.containsAll(listOf("x", "y", "lat", "lng")) == true) {
                SingleCoordinate(
                    x = group["x"]!!,
                    y = group["y"]!!,
                    lat = group["lat"]!!,
                    lng = group["lng"]!!
                )
            } else {
                // 可根据需求调整:抛出异常/跳过该坐标/给默认值
                null
            }
        }

        return MapCoordinate(sortedCoordinates)
    }
}

3. 注册解析器并使用

创建Gson实例时注册自定义解析器,即可正常解析API响应:

val gson = GsonBuilder()
    .registerTypeAdapter(MapCoordinate::class.java, MapCoordinateDeserializer())
    .create()

// 解析API返回的Response<MapLabels>
val response = gson.fromJson(apiResponseString, Response::class.java)

4. Moshi适配器替代方案(若项目用Moshi)

如果项目使用Moshi作为JSON解析库,可编写对应适配器:

class MapCoordinateAdapter {
    @FromJson
    fun fromJson(json: JsonObject): MapCoordinate {
        val coordinateGroups = mutableMapOf<Int, MutableMap<String, String>>()

        json.keys.forEach { key ->
            val value = json[key]?.asString ?: return@forEach
            val matchResult = Regex("([a-z]+)(\\d+)").find(key)
            matchResult?.let {
                val prefix = it.groupValues[1]
                val index = it.groupValues[2].toInt()
                if (!coordinateGroups.containsKey(index)) {
                    coordinateGroups[index] = mutableMapOf()
                }
                coordinateGroups[index]?.put(prefix, value)
            }
        }

        val sortedCoordinates = coordinateGroups.keys.sorted().mapNotNull { index ->
            val group = coordinateGroups[index]
            if (group?.containsAll(listOf("x", "y", "lat", "lng")) == true) {
                SingleCoordinate(
                    x = group["x"]!!,
                    y = group["y"]!!,
                    lat = group["lat"]!!,
                    lng = group["lng"]!!
                )
            } else {
                null
            }
        }

        return MapCoordinate(sortedCoordinates)
    }
}

注册并使用:

val moshi = Moshi.Builder()
    .add(MapCoordinateAdapter())
    .build()

val adapter = moshi.adapter(Response::class.java)
val response = adapter.fromJson(apiResponseString)

核心逻辑说明

  • 正则表达式([a-z]+)(\\d+)精准匹配字段前缀和数字后缀,彻底解决超过9个点时的排序混乱问题(比如x10不会排在x2前面)。
  • 通过数字索引分组+排序,保证最终坐标列表的顺序与标注点的绘制顺序一致。
  • 增加了属性完整性校验,避免后端返回缺失字段导致的解析崩溃。

内容的提问来源于stack exchange,提问作者AmirHossin TaghiPour

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 11:57:35