Ferdinand Lilio
Ferdinand Lilio

Reputation: 51

Deserializing Generic Data types using GSON

my first time to post here.

the json response from my server looks like this

{
  "success": true,
  "message": null,
  "data": {
     "id": 1,
     "name": "1"
  }
}

the data field could be a List<MyModelClass> or it could just be MyModelClass in the above example it is just a single Object.

the field name on the json output exactly matches all my POJO classes.

my response template look like this

import com.google.gson.annotations.Expose;

public class ResponseTemplate<T>{

    @Expose
    private boolean success;
    @Expose
    private String message;
    @Expose
    private T data;

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public boolean isSuccess() {
        return success;
    }

    public void setSuccess(boolean success) {
        this.success = success;
    }

    public T getData() {
        return this.data;
    }

}

then to convert that data from getData() i had to do this

    //.... this is inside a function

    ResponseTemplate response = apiService.getMyObject();
    if (response.isSuccess()) {
        // if its a list
        //Type dataType = new TypeToken<List<MyModelClass>>() {
        //}.getType();

        //if a single object
        String toJson = gson.toJson(response.getData(), MyModelClass.class);
        System.out.println(toJson);
        new Gson().fromJson(gson.toJson(response.getData(), MyModelClass.class), MyModelClass.class);
    } else {
        return null;
    }

then it will give me an error

Exception in thread "main" java.lang.IllegalArgumentException: Can not set int field models.MyModelClass.id to com.google.gson.internal.LinkedTreeMap
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:164)
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:168)
at sun.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:55)
at sun.reflect.UnsafeIntegerFieldAccessorImpl.getInt(UnsafeIntegerFieldAccessorImpl.java:56)
at sun.reflect.UnsafeIntegerFieldAccessorImpl.get(UnsafeIntegerFieldAccessorImpl.java:36)
at java.lang.reflect.Field.get(Field.java:379)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:86)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195)
at com.google.gson.Gson.toJson(Gson.java:593)
at com.google.gson.Gson.toJson(Gson.java:572)
at com.google.gson.Gson.toJson(Gson.java:527)

on this line gson.toJson(response.getData(), MyModelClass.class) it will break.

the strange thing is, it will work if the output of the getData() is List<MyModelClass> but if the output of the getData() is only MyModelClass it Gson can't map it, even though all the field names are properly mapped.

Is there a better way of implementing this? maybe a common deserializer? Ive beent trying to search but can't really find what i needed.

Upvotes: 2

Views: 1555

Answers (1)

Ferdinand Lilio
Ferdinand Lilio

Reputation: 51

i solved my issue by doing this:

//if its a list
//Type dataType = new TypeToken<ResponseTemplate<List<MyModelClass>>>() {}.getType();

//if its a single object
Type dataType = new TypeToken<ResponseTemplate<MyModelClass>>() {}.getType();
ResponseTemplate response = new Gson().fromJson(gson.toJson(apiService.getMyObject(), dataType), dataType);

MyModelClass myModelClass = response.getData();

Upvotes: 3

Related Questions