1

I am trying to convert some JSON into a java object in android, however it does not seem to work.

Gson gson = new Gson();
Person person = gson.fromJson(s, Person.class);
Toast toast = Toast.makeText(getApplicationContext(), "Welcome back " + person.getDisplayName(), duration);
toast.show();

Where Person.class is

com.google.api.services.plus.model.Person

I am getting type conversion errors such as:

wrong object type: Ljava/lang/Double; Ljava/lang/Integer;
java.lang.IllegalArgumentException: invalid value for field

But I want to reuse this model object from the API library, so is there anyway to fix this?

EDIT:

To prove this problem in a more simple form, please refer to this example.

com.google.api.services.plus.model.Person;

Gson g = new Gson();

    Person p1 = new Person();
    p1.setDisplayName("Test");
    p1.setCircledByCount(10);

    String json = g.toJson(p1);
    Person fromJson = g.fromJson(json, Person.class);
    System.out.println(fromJson.getDisplayName());

Throws the same exception.

Exception in thread "main" java.lang.IllegalArgumentException: Can not set java.lang.Integer field com.google.api.services.plus.model.Person.circledByCount to java.lang.Double
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(Unknown Source)
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(Unknown Source)

Am I doing something wrong? Thanks

2
  • 1
    post your model class and json Commented Feb 23, 2014 at 14:55
  • 1
    Quite honestly, you shouldn't be using GSON with that class. It's not designed to be used with GSON. It has it's own built in logic for serializing itself to JSON, and the library it's part of handles deserialization to it. Commented Feb 24, 2014 at 6:33

3 Answers 3

6

The issue is the class you're using isn't meant/designed to be used with Gson.

The core issue is that Person extends GenericJson which extends GenericData which extends AbstractMap<String, Object> ... and that is the problem.

When Gson attempts to deserialize the JSON, it's using its MapTypeAdapterFactory which unfortunately causes the JSON numeric type for "circledByCount" to be read as a Double in Java.

Then the complexity of this Person class kicks in. If you go look at the source code it actually uses annotations and overridden put methods to populate the field in Person. If you look at the stack trace you can actually see what happens:

Exception in thread "main" java.lang.IllegalArgumentException: Can not set java.lang.Integer field com.google.api.services.plus.model.Person.circledByCount to java.lang.Double
    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:164)
    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:168)
    at sun.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:81)
    at java.lang.reflect.Field.set(Field.java:680)
    at com.google.api.client.util.FieldInfo.setFieldValue(FieldInfo.java:245)
    at com.google.api.client.util.FieldInfo.setValue(FieldInfo.java:206)
    at com.google.api.client.util.GenericData.put(GenericData.java:103)
    at com.google.api.client.util.GenericData.put(GenericData.java:47)
    at com.google.gson.internal.bind.MapTypeAdapterFactory$Adapter.read(MapTypeAdapterFactory.java:188)
    at com.google.gson.internal.bind.MapTypeAdapterFactory$Adapter.read(MapTypeAdapterFactory.java:145)
    at com.google.gson.Gson.fromJson(Gson.java:803)
    at com.google.gson.Gson.fromJson(Gson.java:768)
    at com.google.gson.Gson.fromJson(Gson.java:717)
    at com.google.gson.Gson.fromJson(Gson.java:689)

Gson is calling GenericData's put() method (Because, it knows this is a Map). That method actually populates the annotated circledByCount field via reflection. And ... it's the wrong type.

So, basically ... this isn't going to work with Gson. At least not without writing a custom JsonDeserializer but looking at the class, that's going to be rather complicated.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for the detailed explanation. It seems strange to have model classes and to use a different json serializer than GSON when it is used in many other places in the client libs. I'm sure there is a valid reason for this however!
0

Your person class must have the exact same fileds and name as the JSON you parse.

Comments

0

Your JSON String have a Double value and and the Person object you care casting have a Integer value.

Please check the Person object on both sides. Better if you copy and paste the same Person object in Android app side..

2 Comments

They are the same model class from the Google api as listed in the post. The json is generated by a spring mvc controller returning a person object. Could the server side Jackson serializer be causing the issue?
If the JSON string return from the server is oky it cannot be an issue of Jackson serializer. Double check your person class .. If you can provide the JSON string and Person class in both sides server and client side..

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.