jimmyweb jimmyweb - 8 months ago 47
JSON Question

Gson - deserialization to specific object type based on field value

I want to deserialize json objects to specific types of objects (using Gson library) based on

field value, eg.:

"type": "type1",
"id": "131481204101",
"url": "http://something.com",
"name": "BLAH BLAH",
"icon": "SOME_STRING",
"price": "FREE",
"backgroundUrl": "SOME_STRING"

field will have different (but known) values. Based on that value I need to deserialize that json object to appropriate model object, eg.: Type1Model, Type2Model etc.
I know I can easily do that before deserialization by converting it to
, iterate through it and resolve which type it should be deserialized to. But I think it's ugly approach and I'm looking for better way. Any suggestions?


You may implement a JsonDeserializer and use it while parsing your Json value to a Java instance. I'll try to show it with a code which is going to give you the idea:

1) Define your custom JsonDeserializer class which creates different instance of classes by incoming json value's id property:

class MyTypeModelDeserializer implements JsonDeserializer<MyBaseTypeModel> {

  public MyBaseTypeModel deserialize(final JsonElement json, final Type typeOfT, final JsonDeserializationContext context)
      throws JsonParseException {
     JsonObject jsonObject = json.getAsJsonObject();

     JsonElement jsonType = jsonObject.get("type");
     String type = jsonType.getAsString();

     MyBaseTypeModel typeModel = null;     

     if("type1".equals(type)) {
         typeModel = new Type1Model();
     } else if("type2".equals(type)) {
         typeModel = new Type2Model();
     // TODO : set properties of type model

     return typeModel;

2) Define a base class for your different instance of java objects:

class  MyBaseTypeModel {
   private String type;
   // TODO : add other shared fields here

3) Define your different instance of java objects' classes which extend your base class:

class Type1Model extends MyBaseTypeModel {
   // TODO: add specific fields for this class

class Type2Model extends MyBaseTypeModel {
   // TODO: add specific fields for this class

4) Use these classes while parsing your json value to a bean:

GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(MyBaseTypeModel.class, new MyTypeModelDeserializer());
Gson gson = gsonBuilder.create();

MyBaseTypeModel myTypeModel = gson.fromJson(myJsonString, MyBaseTypeModel.class);

I can not test it right now but I hope you get the idea. Also this link would be very helpful.