Deserializing an abstract class in Gson

Viewed 32158

I have a tree object in JSON format I'm trying to deserialize with Gson. Each node contains its child nodes as fields of object type Node. Node is an interface, which has several concrete class implementations. During the deserialization process, how can I communicate to Gson which concrete class to implement when deserializing the node, if I do not know a priori which type the node belongs to? Each Node has a member field specifying the type. Is there a way to access the field when the object is in serialized form, and somehow communicate the type to Gson?

Thanks!

5 Answers

I want to correct the above a little

public class PropertyMarshallerAbstractTask implements JsonSerializer<Object>, JsonDeserializer<Object> {

    private static final String CLASS_TYPE = "CLASS_TYPE";

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

        JsonObject jsonObj = jsonElement.getAsJsonObject();
       String className = jsonObj.get(CLASS_TYPE).getAsString();

        try {
            Class<?> clz = Class.forName(className);
            return jsonDeserializationContext.deserialize(jsonElement, clz);
        } catch (ClassNotFoundException e) {
            throw new JsonParseException(e);
        }
    }

    @Override
    public JsonElement serialize(Object object, Type type, JsonSerializationContext jsonSerializationContext) {
    
        Gson gson = new Gson(); //without this line it will not work
        gson.toJson(object, object.getClass()); //and this one
        JsonElement jsonElement = gson.toJsonTree(object); //it needs to replace to another method...toJsonTree
        jsonElement.getAsJsonObject().addProperty(CLASS_TYPE, object.getClass().getCanonicalName());
        return jsonElement;
    }
}

And then I use it:

Gson gson = new GsonBuilder()
                .registerTypeAdapter(AbstractTask.class, new PropertyMarshallerOfAbstractTask())
                .create();

And then I can parse List (where I keep some non-abstract classes, which inherited from Abstract Task) to Json;

And it works in the opposite direction

List<AbstractTask> abstractTasks = gson.fromJson(json, new TypeToken<List<AbstractTask>>(){}.getType());
Related