Gson - Как разобрать частичный JSON в Kotlin - PullRequest
0 голосов
/ 26 июня 2019

У меня есть 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"}

Ответы [ 3 ]

1 голос
/ 26 июня 2019

Вы пробовали с Any?

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

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

Попробуйте с этим, все получится.

Хорошего дня.:)

1 голос
/ 26 июня 2019

Вы можете использовать JsonDeserializer для вашего класса Model, например:

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))
0 голосов
/ 26 июня 2019

Если адрес сам по себе является действительным json, то вы можете сделать это:

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

Если это строка, то

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