The code is based on the following link: Link
I'm getting a run time exception:
java.lang.UnsupportedOperationException: JsonObject
when running the following code:
data class Student(
var name: String? = null,
var address: String? = null) {
}
class StudentDeserializer : JsonDeserializer<Student> {
override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): Student {
json as JsonObject
val name = json.asString
val addressJson = json.get("address")
val address = if (addressJson.isJsonObject) addressJson.toString() else addressJson.asString
return Student(name, address)
}
}
the error is in:
val name = json.asString
which is part of deserialize method that is probably being called when i'm writing:
val student = gSon.fromJson<Student>(json2, Student::class.java)
When standing over this line and pressing the ctrl + b keyboard, it takes me to JsonElement class and I see the following method:
public String getAsString() {
throw new UnsupportedOperationException(getClass().getSimpleName());
}
as we can see, there is only a throw statement here. But if we read the method documentation we will see that it is written there that the throw statement happen is only part of the method.
/**
* convenience method to get this element as a string value.
*
* @return get this element as a string value.
* @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid
* string value.
* @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
* more than a single element.
*/
public String getAsString() {
...
My questions are:
getAsString
Does it mean that the get() implementation of asString property is: return getAsString(this)?JsonElement::getAsString()
only works for json primitives. Primitives are strings, numbers and booleans. Your json
instance is a JsonObject
and thus not a primitive which means there's no implementation for getAsString()
which returns a meaningful value.
From the tutorial, you actually should do json.get("name").asString
.
json.get("name")
will return the name
element which is of type JsonPrimitive
-> a json primitive on which you can call getAsString()
.
For further clarification, this is the content of json
:
{
"name": "Mark",
"address": {
"city": "London",
"post": "12000"
}
}
and this is the content of json.get("name")
:
"Mark"
which then will result as the string Mark
when getAsString()
/ asString
is called.
Also see: GSON JsonElement.getAsString vs. JsonElement.toString?
For your question about the source code. JsonPrimitive
is a subclass of JsonObject
. When you navigate, the IDE only knows that it must be a JsonObject
, but at runtime, it will see that it's actually a primitive and calls JsonPrimitive::getAsString()
. The source for that is here: https://github.com/google/gson/blob/master/gson/src/main/java/com/google/gson/JsonPrimitive.java#L137-L151
This is a result of gson utilizing inheritance. If you need further assistance to understand this, I recommend reading some beginners material in object-oriented programming for Java.