Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GSON deserialization of a wrapped list of objects

I am trying to de-serialize a list of objects from a JSON response. The JSON array has a key, which is causing issues with using GSON to de-serialize it.

I have about 20 objects similar to this.

public class Device extends Entity {
  String device_id;
  String device_type;
  String device_push_id;
}

For most there is an API method which returns a list of objects. The returned JSON looks like this. Because of other clients, changing the format of the JSON is not a reasonable option at this point.

{
   "devices":[
      {
         "id":"Y3mK5Kvy",
         "device_id":"did_e3be5",
         "device_type":"ios"
      },
      {
         "id":"6ZvpDPvX",
         "device_id":"did_84fdd",
         "device_type":"android"
      }
   ]
}

In order to parse this type of response I'm currently using a mix of org.json methods and Gson.

JSONArray jsonResponse = new JSONObject(response).getJSONArray("devices");

Type deviceListType = new TypeToken<List<Device>>() {}.getType();
ArrayList<Device> devices = gson.fromJson(jsonResponse.toString(), deviceListType);

I'm looking for a cleaner method of doing the deserialization as I'd like to use Retrofit. The answer in Get nested JSON object with GSON using retrofit is close to what I need, but doesn't handle Lists. I've copied the generic version of the answer here:

public class RestDeserializer<T> implements JsonDeserializer<T> {
  private Class<T> mClass;
  private String mKey;

  public RestDeserializer(Class<T> targetClass, String key) {
    mClass = targetClass;
    mKey = key;
  }

  @Override
  public T deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext)
    throws JsonParseException {

    JsonElement value = jsonElement.getAsJsonObject().get(mKey);
    if (value != null) {
      return new Gson().fromJson(value, mClass);
    } else {
      return new Gson().fromJson(jsonElement, mClass);
    }
  }
}

My goal is to have this call "just work".

@GET("/api/v1/protected/devices")
public void getDevices(Callback<List<Device>> callback);
like image 407
Derek Avatar asked Jun 03 '15 15:06

Derek


People also ask

How do I deserialize JSON with Gson?

Deserialization – Read JSON using Gson. Deserialization in the context of Gson means converting a JSON string to an equivalent Java object. In order to do the deserialization, we need a Gson object and call the function fromJson() and pass two parameters i.e. JSON string and expected java type after parsing is finished ...

Is Gson better than Jackson?

ConclusionBoth Gson and Jackson are good options for serializing/deserializing JSON data, simple to use and well documented. Advantages of Gson: Simplicity of toJson/fromJson in the simple cases. For deserialization, do not need access to the Java entities.

How to convert JSON object to Java object using Gson?

A Gson is a json library for java, which is created by Google and it can be used to generate a JSON. By using Gson, we can generate JSON and convert JSON to java objects. We can call the fromJson() method of Gson class to convert a JSON object to Java Object.


1 Answers

Use the below class

public class Devices {

@Expose
private List<Device> devices = new ArrayList<Device>();

/**
* 
* @return
* The devices
*/
public List<Device> getDevices() {
return devices;
}

/**
* 
* @param devices
* The devices
*/
public void setDevices(List<Device> devices) {
this.devices = devices;
}

}

Device class

public class Device extends Entity {
  @Expose
  String id;
   @Expose
  String device_id;
  @Expose
  String device_type;
}

or

public class Device extends Entity {
  @Expose @SerializedName("id")
  String deviceId;
   @Expose @SerializedName("device_id")
  String devicePushId;
  @Expose @SerializedName("device_type")
  String deviceType;
}

update retrofit method to

@GET("/api/v1/protected/devices")
public void getDevices(Callback<Devices> callback);

devices.getDevices() //call inside callback method will give you the list

Also, you wont require the custom deserializer

like image 107
rahulrv Avatar answered Sep 25 '22 02:09

rahulrv