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

如何使用Moshi处理含重复字段的JSON数据?

解决Moshi解析重复JSON字段报错的方案

当使用Moshi解析包含重复字段的JSON时,会触发如下错误:

com.squareup.moshi.JsonDataException: Multiple values for 'name' at $.person.name

触发该错误的典型JSON格式示例:

{
  "name" : "Chuck",
  "age" : 21,
  "name" : "Chuck"
}

已知背景

Moshi官方目前不支持忽略或覆盖重复字段的功能,官方认为这类问题属于API设计层面的缺陷,而非库本身需要解决的问题。此前已有方案将重复字段合并为列表,但如果需要直接忽略重复字段(保留第一个值)或覆盖重复字段(保留最后一个值),可以通过自定义Moshi适配器实现。


方案1:保留最后一个重复字段(覆盖前面的值)

通过自定义适配器,在解析时每次遇到重复字段都覆盖之前的值,最终保留最后出现的字段值。

首先定义实体类:

data class Person(val name: String, val age: Int)

编写自定义适配器:

class PersonAdapter {
    @FromJson
    fun fromJson(reader: JsonReader): Person {
        var name: String? = null
        var age: Int? = null
        
        reader.beginObject()
        while (reader.hasNext()) {
            when (reader.nextName()) {
                "name" -> name = reader.nextString() // 重复字段直接覆盖,保留最后一个值
                "age" -> age = reader.nextInt()
                else -> reader.skipValue() // 跳过未知字段
            }
        }
        reader.endObject()
        
        return Person(name ?: "", age ?: 0) // 根据业务需求处理空值情况
    }
}

注册适配器到Moshi并使用:

val moshi = Moshi.Builder()
    .add(PersonAdapter())
    .build()
val personAdapter = moshi.adapter(Person::class.java)
val targetPerson = personAdapter.fromJson(yourJsonString)

方案2:保留第一个重复字段(忽略后续重复值)

修改适配器逻辑,仅在字段未赋值时读取,后续重复字段直接跳过。

自定义适配器代码:

class PersonAdapter {
    @FromJson
    fun fromJson(reader: JsonReader): Person {
        var name: String? = null
        var age: Int? = null
        
        reader.beginObject()
        while (reader.hasNext()) {
            val fieldName = reader.nextName()
            when (fieldName) {
                "name" -> {
                    if (name == null) { // 仅读取第一个出现的字段值
                        name = reader.nextString()
                    } else {
                        reader.skipValue() // 跳过后续重复字段
                    }
                }
                "age" -> age = reader.nextInt()
                else -> reader.skipValue()
            }
        }
        reader.endObject()
        
        return Person(name ?: "", age ?: 0)
    }
}

注册和使用方式与方案1一致。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 01:16:08