Gson - 如何在 Kotlin 中解析部分 json
Posted
技术标签:
【中文标题】Gson - 如何在 Kotlin 中解析部分 json【英文标题】:Gson - How to parse partial json in Kotlin 【发布时间】: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 ComponentInfocom.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"
【问题讨论】:
【参考方案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,以便将地址对象作为字符串分配给模型的地址字段。以上是关于Gson - 如何在 Kotlin 中解析部分 json的主要内容,如果未能解决你的问题,请参考以下文章
如何在 kotlin 中通过 GSON lib 解析 JSON 时管理 android 应用程序的空值
如何在 Android 的 Kotlin 中使用 GSON 将 JSON 对象转换为 JSON 数组
如何使用带有 Kotlin 的 Gson 库访问 JSON 有效负载中的嵌套值