Gson在json中存储对象类型

时间:2017-07-29 23:20:01

标签: java json serialization gson

我需要将对象从一个套接字发送到另一个套接字,我想使用JSON进行序列化。 每个json对象都需要存储其类型。我的计划是包裹我的物品:

{
   /* the type */ "_type_": "my.package.MyClass",
   /* the actual object */ "_data_": {
      ...
   }
}

我尝试通过编写此序列化适配器来实现此功能

Gson gson = new GsonBuilder().registerTypeAdapter(Wrapper.class, new ObjectWrapperAdapter()).create();
gson.toJson(new Wrapper(myObject), Wrapper.class);

private static class ObjectWrapperAdapter implements JsonSerializer<Wrapper>, JsonDeserializer<Wrapper> {
    private static final String TYPE_KEY = "__type__";
    private static final String DATA_KEY = "__data__";

    @Override
    public Wrapper deserialize(JsonElement json, Type type, JsonDeserializationContext context) throws JsonParseException {
        if(!json.isJsonObject()) throw new JsonParseException("element is not an object!");
        JsonObject object = json.getAsJsonObject();
        if(!object.has(TYPE_KEY)) throw new JsonParseException(TYPE_KEY + " element is missing!");
        if(!object.has(DATA_KEY)) throw new JsonParseException(DATA_KEY + " element is missing!");
        JsonElement dataObject = object.get(DATA_KEY);
        String clazzName = object.get(TYPE_KEY).getAsString();
        Class<?> clazz = classForName(clazzName);
        return new Wrapper(context.deserialize(dataObject, clazz));
    }

    private Class<?> classForName(String name) throws JsonParseException {
        try {
            return Class.forName(name);
        } catch (ClassNotFoundException e) {
            throw new JsonParseException(e);
        }
    }

    @Override
    public JsonElement serialize(Wrapper src, Type type, JsonSerializationContext context) {
        JsonObject wrapper = new JsonObject();
        Object data = src.object;
        JsonElement dataElement = context.serialize(data);
        String className = data.getClass().getName();
        wrapper.addProperty(TYPE_KEY, className);
        wrapper.add(DATA_KEY, dataElement);
        return wrapper;
    }
}

public static class Wrapper {
    private final Object object;

    public Wrapper(Object object) {
        this.object = object;
    }
}

从理论上讲,这是可行的,但是当我尝试序列化嵌套对象时,它会失败,就像这样

class MyType {
    AnotherType anotherType;
}

因为只会包装MyType并且生成的json看起来像这样:

{
    "__type__": "my.package.MyType",
    "__data__": {
        (No "__type__" field here...)
        ...
    }
}

是否可以使用类似的类型序列化对象?

1 个答案:

答案 0 :(得分:0)

This answer介绍了如何解决此问题。它不使用Gson而是使用Genson。我真的不喜欢Genson如何处理Pojos,但我想我必须忍受它。