Reputation: 40186
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)
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"}
Upvotes: 1
Views: 1450
Reputation: 21
Please try with Any
, it should work.
var address: String? = null
Upvotes: 1
Reputation: 535
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))
Upvotes: 2
Reputation: 836
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. :)
Upvotes: 3
Reputation: 113
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()
Upvotes: -1