DorVak
DorVak

Reputation: 337

Why am I getting the java.lang.UnsupportedOperationException when using Gson.asString?

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:

  1. Where is the full implementation?
  2. Why when I click on the ctrl + b in a code like: someJsonObject.asString , that I guess that it's a property, it takes me to method with the name: getAsString Does it mean that the get() implementation of asString property is: return getAsString(this)?

Upvotes: 2

Views: 1310

Answers (2)

Kazakov Vsevolod
Kazakov Vsevolod

Reputation: 28

This way was used in my case:

  1. Make JsonObject from jsonBody val jsonObject = JsonParser.parseString(jsonBody).getAsJsonObject()
  2. Do something with JsonObject
  3. Final step:get Json as String using gsonBuilder String updateBody = GsonBuilder().setPrettyPrinting().create().toJson(jsonObject)

Upvotes: 0

JensV
JensV

Reputation: 4544

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.

Upvotes: 3

Related Questions