Вопрос:

java.lang.IllegalArgumentException while deserializing JSON through GSON

java android json gson

415 просмотра

1 ответ

6446 Репутация автора

I have a model class that I want to serialize/deserialize through GSON while sending it to an Android service:

public final class SearchTutorsQuery extends com.google.api.client.json.GenericJson {
    @com.google.api.client.util.Key
    private com.learncity.searchApi.model.LatLng location;
    @com.google.api.client.util.Key
    private java.util.List<java.lang.String> subjects;
    @com.google.api.client.util.Key
    private com.learncity.searchApi.model.TutorProfileResponseView tutorProfileResponseView;
    @com.google.api.client.util.Key
    private java.util.List<java.lang.String> tutorTypes;

    public SearchTutorsQuery() { /* compiled code */ }

}

I am getting an exception while deserializing the JSON string:

java.lang.IllegalArgumentException: field com.learncity.searchApi.model.SearchTutorsQuery.tutorProfileResponseView has type com.learncity.searchApi.model.TutorProfileResponseView, got com.google.gson.internal.LinkedTreeMap
                      at java.lang.reflect.Field.set(Native Method)
                      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:887)
                      at com.google.gson.Gson.fromJson(Gson.java:852)
                      at com.google.gson.Gson.fromJson(Gson.java:801)
                      at com.google.gson.Gson.fromJson(Gson.java:773)
                      at com.learncity.learner.search.SearchService$SearchHandler.handleMessage(SearchService.java:66)
                      at android.os.Handler.dispatchMessage(Handler.java:102)
                      at android.os.Looper.loop(Looper.java:154)
                      at android.app.ActivityThread.main(ActivityThread.java:6077)
                      at java.lang.reflect.Method.invoke(Native Method)
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)

Here is the TutorProfileResponseView that is giving exception:

public final class TutorProfileResponseView extends com.google.api.client.json.GenericJson {
    @com.google.api.client.util.Key
    private java.lang.Integer disciplines;
    @com.google.api.client.util.Key
    private com.learncity.searchApi.model.EducationalQualificationResponseView educationalQualification;
    @com.google.api.client.util.Key
    private com.learncity.searchApi.model.EducationalQualificationResponseView educationalQualifications;
    @com.google.api.client.util.Key
    private java.lang.Integer global;
    @com.google.api.client.util.Key
    private java.lang.Integer mCurrentStatus;
    @com.google.api.client.util.Key
    private java.lang.Integer mDisplayPicturePath;
    @com.google.api.client.util.Key
    private java.lang.Integer mEmailID;
    @com.google.api.client.util.Key
    private com.learncity.searchApi.model.LatLngResponseView mLastKnownGeoCoordinates;
    @com.google.api.client.util.Key
    private java.lang.Integer mName;
    @com.google.api.client.util.Key
    private java.lang.Integer mPassword;
    @com.google.api.client.util.Key
    private java.lang.Integer mPhoneNo;
    @com.google.api.client.util.Key
    private java.lang.Integer nil;
    @com.google.api.client.util.Key
    private com.learncity.searchApi.model.OccupationResponseView occupation;
    @com.google.api.client.util.Key
    private java.lang.Integer rating;
    @com.google.api.client.util.Key
    private com.learncity.searchApi.model.CreditsResponseView teachingCredits;
    @com.google.api.client.util.Key
    private java.lang.Integer tutorTypes;

    public TutorProfileResponseView() { /* compiled code */ }
}

In case you want to know, the class hierarchy for com.google.api.client.json.GenericJson here is:

java.lang.Object
    java.util.AbstractMap<String,Object>
        com.google.api.client.util.GenericData
            com.google.api.client.json.GenericJson 

I have tried putting the below 2 rules in proguard file:

-keep class com.google.gson.stream.** { *; }
-keep class com.learncity.searchApi.model.** { *; }

Does anyone have any idea of what I am missing?

Автор: pulp_fiction Источник Размещён: 04.03.2017 09:26

Ответы (1)


0 плюса

6446 Репутация автора

Intuitively looking at the problem, it shouldn't exist but the the class java.util.AbstractMap<String,Object> has the twist here. I tried a custom TypeAdapter for the Gson but it didn't work out. I could have written a custom deserializer but as the model of my data changes, I would have a new dependency to take care of at that time so a custom deserializer is far from ideal solution here. I tried to find problem with the everything except my own class which extends from java.util.AbstractMap<String,Object>. You can see that it has Object as type parameter which allows putting anything into the map. There is no type info. present(as per the class) that Gson or any other JSON deserializer can use to figure out the right type.

The solution now is - there is not one with Gson or a JSON deserializer but this is an indicator you must change your model structure or make changes to some other design decision in your application. I ended up doing changes in the design to get around this.

Of course, if you know the type beforehand, a TypeAdapter or deserializer would probably solve your problem.

Автор: pulp_fiction Размещён: 11.03.2017 08:13
Вопросы из категории :
32x32