1 year ago

#388347

test-img

David Wood

How to write an interface type adapter for gson without infinite recursion/stackoverflow

I'm trying to write a generic handler for de/serializing interfaces using Gson and getting stack overflow. I've followed a couple of examples at https://technology.finra.org/code/serialize-deserialize-interfaces-in-java.html and https://paul-stanescu.medium.com/custom-interface-adapter-to-serialize-and-deserialize-interfaces-in-kotlin-using-gson-8539c04b4c8f (which seem to be duplicates of each other). If I run these, serializing a simple class, I get stack overflow. I'm using Gson 2.8.5. I guess its fairly clear that it is trying to call the type adapter again when trying to get the value for the DATA element. Searched around, but haven't seen anything. Any help is much appreciated. Thanks.

import java.lang.reflect.Type;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;

public class InterfaceAdapter<INTERFACE> implements JsonSerializer<INTERFACE>, JsonDeserializer<INTERFACE> {

    private static final String CLASSNAME = "CLASSNAME";
    private static final String DATA = "DATA";

    public INTERFACE deserialize(JsonElement jsonElement, Type type,
        JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {

        JsonObject jsonObject = jsonElement.getAsJsonObject();
        JsonPrimitive prim = (JsonPrimitive) jsonObject.get(CLASSNAME);
        String className = prim.getAsString();
        Class<INTERFACE> klass = getObjectClass(className);
        return jsonDeserializationContext.deserialize(jsonObject.get(DATA), klass);
    }

    
    public JsonElement serialize(INTERFACE jsonElement, Type type, JsonSerializationContext jsonSerializationContext) {
        JsonObject jsonObject = new JsonObject();
        jsonObject.addProperty(CLASSNAME, jsonElement.getClass().getName());
        jsonObject.add(DATA, jsonSerializationContext.serialize(jsonElement));
        return jsonObject;
    }

    public Class getObjectClass(String className) {
        try {
            return Class.forName(className);
        } catch (ClassNotFoundException e) {
            throw new JsonParseException(e.getMessage());
        }
    }
    
    public static class Dummy {
        int a= 1;
    }

    public static void main(String args[]) {
        Gson gson = new GsonBuilder().registerTypeHierarchyAdapter(Dummy.class, new InterfaceAdapter()).create();
        Dummy d = new Dummy();
        String json = gson.toJson(d);
        System.out.println(json);
    }
}

java

json

gson

0 Answers

Your Answer

Accepted video resources