简体   繁体   中英

Gson - How to parse partial json in Kotlin

I have a data class called Model ,

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

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

I have two json strings,

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

Below conversion is working fine,

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

But, this version does not work. Giving an exception.

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

Exception:

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

How can i parse json2 so that address field will be holding the string value of the inner address json data? For example after parsing address should be equal to

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

Did you try with the Any ?

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

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

Try with this, it will work.

Have a good day. :)

You may use a JsonDeserializer specialized for your Model class, like so:

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

Which outputs:

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

If you use the Kotson library, which seems you are, things get even better:

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

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

var address: String? = null

If address is a valid json by it self then you can do this:

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

If it is a string then

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM