在 Moshi 中解析来自 JSON 的内部映射

Parse internal map from JSON in Moshi

我正在尝试使用 moshi 解析以下 JSON,但我无法动态处理美国或英国等数据。 USAUK 是动态键。

 {
"USA": {
    "name": "United State of America",
    "code": "US"
},
"UK": {
    "name": "United Kingdom",
    "code": "UK"
},
  "soft_update": "500",
  "hard_update": "500"
}

数据class:

data class ApiAppUpdate(val countryMap: Map<String, ApiCountry>,
                     @field:Json(name = "hard_update")
                     val forceUpdateVersion: Int,
                     @field:Json(name = "soft_update")
                     val softUpdateVersion: Int)

以下是我的 json 适配器代码:

fun getConfig(){
     val adapter: JsonAdapter<ApiAppUpdate> = moshi.adapter(ApiAppUpdatee::class.java)
}

我获得了软更新值和硬更新值,但 countryMap 始终为空。我不确定这里出了什么问题。有人可以帮帮我吗。谢谢。

问题是您的模型描述会匹配此 json 而不是您附加的:

{
   "countryMap":{
      "USA":{
         "name":"United State of America",
         "code":"US"
      },
      "UK":{
         "name":"United Kingdom",
         "code":"UK"
      }
   },
   "soft_update":"500",
   "hard_update":"500"
}

在您的示例中,"USA""UK""soft_update""hard_update" 处于同一级别。

更新:

这是一个可行的解决方案:

data class ApiCountry(val name: String, val code: String)

data class ApiAppUpdate(
    val countryMap: Map<String, ApiCountry>,
    @field:Json(name = "hard_update")
    val forceUpdateVersion: Int,
    @field:Json(name = "soft_update")
    val softUpdateVersion: Int
)

class ApiUpdateAdapter {

    @FromJson
    fun fromJson(reader: JsonReader): ApiAppUpdate {
        var forceUpdateVersion: Int = -1
        var softUpdateVersion: Int = -1
        val map: MutableMap<String, ApiCountry> = mutableMapOf()

        reader.beginObject()
        while (reader.hasNext()) {
            when (reader.peek()) {
                JsonReader.Token.NAME ->
                    when (val fieldName = reader.nextName()) {
                        "hard_update" -> forceUpdateVersion = reader.nextInt()
                        "soft_update" -> softUpdateVersion = reader.nextInt()
                        else -> {
                            reader.beginObject()
                            var name = ""
                            var code = ""
                            while (reader.hasNext()) {
                                when (reader.nextName()) {
                                    "name" -> name = reader.nextString()
                                    "code" -> code = reader.nextString()
                                    else -> reader.skipValue()
                                }
                            }
                            reader.endObject()
                            map[fieldName] = ApiCountry(name, code)
                        }
                    }
                else -> reader.skipValue()
            }
        }
        reader.endObject()

        return ApiAppUpdate(map, forceUpdateVersion, softUpdateVersion)
    }
}

fun main() {
    val sourceJson =
        "{\"USA\":{\"name\":\"United States of America\",\"code\":\"US\"},\"UK\":{\"name\":\"United Kingdom\",\"code\":\"UK\"}" +
                ",\"soft_update\":\"200\",\"hard_update\":\"300\"}"

    val adapter = Moshi.Builder()
        .add(ApiUpdateAdapter())
        .build()
        .adapter(ApiAppUpdate::class.java)

    val apiAppUpdate = adapter.fromJson(sourceJson)

    println(apiAppUpdate)
}