2

I have following json:

{
    "list": [
        {
            "BaseClass": {
                "id": 0
            }
        },
        {
            "ExtendedClass1": {
                "id": 1,
                "sum": 100
            }
        },
        {
            "ExtendedClass1_1": {
                "id": 2,
                "sum": 200,
                "expr": "text"
            }
        },
        {
            "ExtendedClass2": {
                "id": 3,
                "total": 300
            }
        }
    ]
}

Also I have following classes with declared inheritance:

MetaClass.java

import java.util.ArrayList;

import com.google.gson.Gson;

public class MetaClass{

    public ArrayList<BaseClass> list = new ArrayList<BaseClass>();

    public static void main(String[] args) {

        String json = "{\"list\":[{\"BaseClass\":{\"id\":0}},{\"ExtendedClass1\":{\"id\":1,\"sum\":100}},{\"ExtendedClass1_1\":{\"id\":2,\"sum\":200,\"expr\":\"text\"}},{\"ExtendedClass2\":{\"id\":3,\"total\":300}}]}";  

        MetaClass gson = new Gson().fromJson(json, MetaClass.class);

        }

 }

BaseClass.java

public class BaseClass{
    public int id;   
    public BaseClass() {   
    }
 }

ExtendedClass1.java

public class ExtendedClass1 extends BaseClass{
    public ExtendedClass1() {
    }
    public int sum;
}

ExtendedClass2.java

public class ExtendedClass2 extends BaseClass {
    public ExtendedClass2() {
    }
    public int total;
}

ExtendedClass1_1.java

public class ExtendedClass1_1 extends ExtendedClass1 {   
    public ExtendedClass1_1() {       
    }
    public String expr;
}

Also, there could be a lot of such classes with multilevel inheritance. I try to make this example simpler. How correctly parse mentioned json string? Assume please that I could not change input json, only I can change classes and write custom fromJson command somehow...

EDIT: Of course, I can add to BaseClass.java all attributes that could be met in json (see below), but it seems not elegant solution.

public ExtendedClass1 ExtendedClass1;
public ExtendedClass2 ExtendedClass2;
public ExtendedClass1_1 ExtendedClass1_1;
Anton
  • 539
  • 6
  • 14

1 Answers1

0

You can write a custom TypeAdapter and register it to gsonBuilder. In your custom type adapter's read method, you have to manage mappings to create correct instances of the classes that you defined. I used the tags of your list json array's items:

public class CustomTypeAdapter extends TypeAdapter<BaseClass> {

    @Override
    public BaseClass read(JsonReader in) throws IOException {
        BaseClass item = null;

        Gson gson = new Gson();

        JsonParser jsonParser = new JsonParser();
        JsonObject jo = (JsonObject)jsonParser.parse(in);

        JsonElement je = null;
        if ((je = jo.get("BaseClass")) != null) {
            item = gson.fromJson(je, BaseClass.class);
        } else if((je = jo.get("ExtendedClass1")) != null) {
            item = gson.fromJson(je, ExtendedClass1.class);
        } else if((je = jo.get("ExtendedClass1_1")) != null) {
            item = gson.fromJson(je, ExtendedClass1_1.class);
        } else if((je = jo.get("ExtendedClass2")) != null) {
            item = gson.fromJson(je, ExtendedClass2.class);
        }

        return item;
    }

    @Override
    public void write(JsonWriter out, BaseClass item) throws IOException {
        throw new IllegalArgumentException("TypeAdapter.write method not implemented!");
    }
}

Test:

String json = "{\"list\":[{\"BaseClass\":{\"id\":0}},{\"ExtendedClass1\":{\"id\":1,\"sum\":100}},{\"ExtendedClass1_1\":{\"id\":2,\"sum\":200,\"expr\":\"text\"}},{\"ExtendedClass2\":{\"id\":3,\"total\":300}}]}";

GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(BaseClass.class, new CustomTypeAdapter());
Gson gson = gsonBuilder.create();

java.lang.reflect.Type listType = new com.google.gson.reflect.TypeToken<List<BaseClass>>() {}.getType();

JsonArray jsonList = (JsonArray) (gson.fromJson(json, JsonObject.class).get("list"));
List<BaseClass> itemList = gson.fromJson(jsonList, listType);
Devrim
  • 15,345
  • 4
  • 66
  • 74