flo3573358
flo3573358

Reputation: 7

Retrofit android: gson array content deserialization

I'm working on API Requests with Retrofit(1.9.0) and gson library (1.7.0 I have compatibility issues with version 2.3.1 of gson) on Android, I make some request to an API which have same format of response but different content following the url call, but I encounter a problem for a deserialization of one answer which there is array inside. This is an example of the json I want to deserialize :

{
   "http_code":200,
   "content":[
      {
         "name":"Groult Christian",
         "location":[
            48.897655,
            2.252462
         ],
         "website":null,
         "address":{
            "street_address":"XXXXXX",
            "city":"XXXXXX",
            "state":null,
            "postal_code":"XXXXXX",
            "country":"XXXXXX"
         },
         "global_score":0,
         "popularity_score":0,
         "quality_score":0,
         "createdAt":"2015-02-18T02:13:05.068Z",
         "updatedAt":"2015-02-18T02:13:05.068Z",
         "id":"54e3f531775288ca572872ac"
      },
      ...
   ]
}

My DeserializerJson and how I call it for retrofit:

    public class DeserializerJson<T> implements JsonDeserializer<T> {

        @Override
        public T deserialize(JsonElement je, Type type, JsonDeserializationContext jdc)
                throws JsonParseException
        {
            // Get the "content" element from the parsed JSON
            JsonElement content = je.getAsJsonObject().get("content");

            // Deserialize it. You use a new instance of Gson to avoid infinite recursion
            // to this deserializer
            return new Gson().fromJson(content, type);

        }
    }
...
Gson gson = new GsonBuilder()
                .registerTypeAdapter(ContentUser.class, new DeserializerJson<ContentUser>())
                .registerTypeAdapter(DeviceInfo.class, new DeserializerJson<DeviceInfo>())
                .registerTypeAdapter(PlacesModel.class, new DeserializerJson<PlacesModel>())
                .create();

        RestAdapter restAdapter = new RestAdapter.Builder()
                .setLogLevel(RestAdapter.LogLevel.BASIC)
                .setConverter(new GsonConverter(gson))
                ...
...

and my different models:

public class PlacesModel {
    @SerializedName("name")
    @Expose
    private String name;
    @SerializedName("location")
    @Expose
    private List<Double> location = new ArrayList<Double>();
    @SerializedName("website")
    @Expose
    private Object website;
    @SerializedName("address")
    @Expose
    private AddressModel address;
    @SerializedName("global_score")
    @Expose
    private Integer globalScore;
    @SerializedName("popularity_score")
    @Expose
    private Integer popularityScore;
    @SerializedName("quality_score")
    @Expose
    private Integer qualityScore;
    @SerializedName("createdAt")
    @Expose
    private String createdAt;
    @SerializedName("updatedAt")
    @Expose
    private String updatedAt;
    @Expose
    @SerializedName("id")
    private String id;

   /* Getters and Setters... */
}

public class AddressModel {

    @SerializedName("street_address")
    @Expose
    private String streetAddress;
    @SerializedName("city")
    @Expose
    private String city;
    @SerializedName("state")
    @Expose
    private Object state;
    @SerializedName("postal_code")
    private String postalCode;
    @SerializedName("country")
    @Expose
    private String country;

    /* Getters and Setters... */
}

url call in Api Manager is like this:

@GET("/places")
public void getPlaces(RestCallback<List<PlacesModel>> callback);

But when I do the call I get this error : com.google.gson.JsonParseException: The JsonDeserializer com.google.gson.DefaultTypeAdapters$CollectionTypeAdapter@3b8aa06 failed to deserialize json object

Everything is fine for other call I get all content and so with no problem but one where there is array inside content I got an error and I don't understand why I believed if I just put a list of my model it will be fine but it doesn't work. I think I miss something so if someone can help me

Thanks in advance

Upvotes: 0

Views: 3313

Answers (1)

Konrad Krakowiak
Konrad Krakowiak

Reputation: 12365

The problem of your issue is that you register DeserializerJson for PlacesModel class and in getPlaces method your response is List<PlacesModel> class. List<PlacesModel> is a different class as PlacesModelso Gson doesn't know how to deserialise List<PlacesModel>. What you have to do is register one more Deserialiser by this method:

.registerTypeAdapter(List.class, new DeserializerJson<List<PlacesModel>>())

If you use more than one type of List (I mean List<PlacesModel> and List< DeviceInfo >) You can define your own TypeAdapter or you cN change list to array and register deserialiser for them as is shown below

.registerTypeAdapter(PlacesModel[].class, new DeserializerJson<PlacesModel[]>())

Now everything works fine for yours json.

Upvotes: 1

Related Questions