3

I am trying to parse following JSON using moshi but I am unable to dynamic data like USA or UK. USA and UK are dynamic keys.

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

Data 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)

Following is my json adapter code:

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

I get soft and hard update values but countryMap is always null. I am not sure what's wrong in here. Can someone please help me. Thanks.

user1288005
  • 890
  • 2
  • 16
  • 36

1 Answers1

2

The problem is that your model description would match this json and not the one you attached:

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

In your example "USA" and "UK" are on the same level with "soft_update" and "hard_update".

UPDATE:

This is a working solution:

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)
}
adrianbukros
  • 326
  • 2
  • 7