【问题标题】:Gson - How to parse partial json in KotlinGson - 如何在 Kotlin 中解析部分 json
【发布时间】:2019-11-08 08:08:26
【问题描述】:

我有一个data class,叫做Model

data class Model(var name: String? = null, var address: String? = null) {

    override fun toString(): String {
        return "name: $name address: $address"
    }
}

我有两个 json 字符串,

val json1 = "{ \"name\": \"Alex\", \"address\": \"rome, 1000\" }"
val json2 = "{ \"name\": \"Alex\", \"address\": {\"city\": \"rome\", \"post\": \"1000\" } }"

下面的转换工作正常,

val model1 = Gson().fromJson<Model>(json1, Model::class.java)

但是,这个版本不工作。给出一个例外。

val model2 = Gson().fromJson<Model>(json2, Model::class.java)

例外:

E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.achellies.kotlin, PID: 11211
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.achellies.kotlin/com.achellies.kotlin.MainActivity}: com.google.gson.JsonSyntaxException: com.google.gson.stream.MalformedJsonException: Unterminated object at line 1 column 40 path $.address
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3086)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3229)
    at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
    at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1926)
    at android.os.Handler.dispatchMessage(Handler.java:106)
    at android.os.Looper.loop(Looper.java:214)
    at

如何解析json2 以便address 字段将保存内部地址json 数据的字符串值?例如解析后address应该等于

{"city": "rome", "post": "1000"}

【问题讨论】:

    标签: android json parsing kotlin gson


    【解决方案1】:

    你试过Any吗?

    data class Model(var name: String? = null, var address: Any? = null) {
    
        override fun toString(): String {
            return "name: $name address: $address"
        }
    }
    

    试试这个,它会工作的。

    祝你有美好的一天。 :)

    【讨论】:

      【解决方案2】:

      您可以使用专门用于您的 Model 类的 JsonDeserializer,如下所示:

      fun main() {
          val json1 = "{ \"name\": \"Alex\", \"address\": \"rome, 1000\" }"
          val json2 = "{ \"name\": \"Alex\", \"address\": {\"city\": \"rome\", \"post\": \"1000\" } }"
      
          val gson = GsonBuilder().registerTypeAdapter(Model::class.java, ModelDeserializer()).create()
      
          println(gson.fromJson(json1, Model::class.java))
          println(gson.fromJson(json2, Model::class.java))
      }
      
      data class Model(val name: String, val address: String)
      
      class ModelDeserializer : JsonDeserializer<Model> {
      
          override fun deserialize(json: JsonElement, typeOfT: Type, context:     JsonDeserializationContext): Model {
              json as JsonObject
      
              val name = json.get("name").asString
      
              val addressJson = json.get("address")
              val address = if (addressJson.isJsonObject) addressJson.asJsonObject.toString() else addressJson.asString
      
              return Model(name, address)
          }
      }
      

      哪些输出:

      Model(name=Alex, address=rome, 1000)
      Model(name=Alex, address={"city":"rome","post":"1000"})
      

      如果你使用 Kotson 库,看起来你就是这样,事情会变得更好:

      val gson = GsonBuilder()
              .registerTypeAdapter<Model> {
                  deserialize {
                      val json = it.json.asJsonObject
      
                      val name = json["name"].asString
      
                      val addressJson = json["address"]
                      val address = if (addressJson.isJsonObject) addressJson.asJsonObject.toString() else addressJson.asString
      
                      Model(name, address)
                  }
              }
              .create()
      
      println(gson.fromJson<Model>(json1))
      println(gson.fromJson<Model>(json2))
      

      【讨论】:

      • 非常感谢。它有帮助。
      【解决方案3】:

      请尝试Any,它应该可以工作。

      var address: String? = null
      

      【讨论】:

        【解决方案4】:

        如果地址本身是一个有效的 json,那么你可以这样做:

        val jsonObject = JSONObject(jsonString)
        val address = jsonObject.optJSONObject("address").toString()
        

        如果是字符串则

        val address = jsonObject.optString("address").toString()
        

        【讨论】:

        • 但我需要将其解析为模型对象。我该怎么做?
        • 您需要在这两种情况下都适用的解决方案吗?一种情况是只有城市名称在 json 中,而另一种情况是它可以是整个城市对象?或者你只是想让它适用于 json2?
        • 我想使用 Gson 库解析 json2,以便将地址对象作为字符串分配给模型的地址字段。
        猜你喜欢
        • 1970-01-01
        • 2022-12-01
        • 2018-01-18
        • 2021-09-30
        • 1970-01-01
        • 2014-05-10
        • 2018-07-23
        • 2017-06-15
        相关资源
        最近更新 更多