Java Json:使用接口泛型类型列表反序列化接口类

Java Json:使用接口泛型类型列表反序列化接口类,java,json,gson,Java,Json,Gson,我根据用户类型序列化UserInterface类型的子类。这些子类有一个列表。角色也是一个接口。我已经编写了自定义Gson适配器: public class InterfaceAdapter<T> implements JsonSerializer<T>, JsonDeserializer<T> { public JsonElement serialize(T object, Type interfaceType, JsonSerializationConte

我根据用户类型序列化UserInterface类型的子类。这些子类有一个列表。角色也是一个接口。我已经编写了自定义Gson适配器:

public class InterfaceAdapter<T> implements JsonSerializer<T>, JsonDeserializer<T> {
public JsonElement serialize(T object, Type interfaceType, JsonSerializationContext context) {
    final JsonObject wrapper = new JsonObject();
    wrapper.addProperty("type", object.getClass().getName());
    wrapper.add("data", context.serialize(object));
    return wrapper;
}

public T deserialize(JsonElement elem, Type interfaceType, JsonDeserializationContext context) throws JsonParseException {
    final JsonObject wrapper = (JsonObject) elem;
    final JsonElement typeName = get(wrapper, "type");
    final JsonElement data = get(wrapper, "data");
    final Type actualType = typeForName(typeName);
    return context.deserialize(data, actualType);
}

private Type typeForName(final JsonElement typeElem) {
    try {
        return Class.forName(typeElem.getAsString());
    } catch (ClassNotFoundException e) {
        throw new JsonParseException(e);
    }
}

private JsonElement get(final JsonObject wrapper, String memberName) {
    final JsonElement elem = wrapper.get(memberName);
    if (elem == null) throw new JsonParseException("no '" + memberName + "' member found in what was expected to be an interface wrapper");
    return elem;
}
}
编辑: 这个问题被标记为重复问题。但是,标记的问题回答了如何反序列化接口类型(而不是以最智能的方式)。我的问题不在那。我知道如何反序列化顶级接口类型。在我的例子中,我有一个接口的基本实现,它有另一个接口类型的列表。这门课用于作文。 想象一下:

interface IA {}

interface IR {}

class R1 implements IR {}

class R2 implements IR {}

class A1 implements IA {
    private List<IR> list;
}

class A2 implements IA {
    private A1 member;
}

class A3 implements IA {
    private A1 member;
}
接口IA{}
接口IR{}
类R1实现IR{}
类R2实现IR{}
A1类实现IA{
私人名单;
}
A2类实现IA{
私人A1会员;
}
A3类实现IA{
私人A1会员;
}

反序列化
私有列表时出现问题

我不确定您是否正确注册了类型适配器(您是否为每个类使用了
registerTypeHierarchyAdapter
registerTypeAdapter
),但您面临着一个典型问题,您必须存储一个正确的类名(甚至包括泛型的类型名)才能按其具体类型检索对象。不幸的是,
InstanceCreator
无法帮助您,因为它只能接受特定类型
RuntimeTypeAdapterFactory
,作为Google Gson extras的一部分实现,设计用于处理类型别名,因此您必须映射每个已知接口

无论如何,只要实现一个合适的类型适配器工厂,就可以使它完全不依赖于接口。例如:

final class InterfaceTypeAdapterFactory
实现TypeAdapterFactory{
//实际上是一个完全没有国家的单身汉
私有静态最终类型适配器工厂interfaceTypeAdapterFactory=新interfaceTypeAdapterFactory();
专用接口PeaDapterFactory(){
}
//但是,让我们封装实例化
静态类型适配器工厂getInterfaceTypeAdapterFactory(){
返回接口PEADAPTERFACTORY;
}
@凌驾
公共类型适配器创建(最终Gson Gson、最终TypeToken TypeToken){
//检查它是否是一个接口
return!typeToken.getRawType().isInterface()
//如果不是,那么就让Gson选择一个合适的类型适配器
无效的
//否则,返回空安全自定义类型适配器
:新的InterfaceTypeAdapter(gson).nullSafe();
}
私有静态最终类InterfaceTypeAdapter
扩展类型适配器{
私有静态最终字符串类型\u PROPERTY=“TYPE”;
私有静态最终字符串数据\u PROPERTY=“DATA”;
私人最终Gson Gson;
专用接口适配器(最终Gson Gson){
this.gson=gson;
}
@凌驾
@抑制警告(“资源”)
公共无效写入(最终JsonWriter out,最终T值)
抛出IOException{
//这里我们只是写了一个类似于您所做的属性值
out.beginObject();
out.name(类型_属性);
out.value(value.getClass().getName());
out.名称(数据属性);
toJson(value,value.getClass(),out);
out.endObject();
}
@凌驾
公共T读(最终JsonReader in)
抛出IOException{
试一试{
//反序列化更为复杂
//确保当前值是一个对象
in.beginObject();
最终字符串名称=in.nextName();
最终目标值;
交换机(名称){
//如果流中的第一个属性是类型。。。
案例类型\u属性:
最终字符串类型=in.nextString();
//然后要求下一个属性为数据
如果(!in.nextName().equals(数据属性)){
抛出新的MalformedJsonException(“预期”+DATA_属性+”位于“+in”);
}
//并将反序列化委托给Gson
value=gson.fromJson(in,Class.forName(type));
打破
//如果由于某种原因,数据和类型的顺序混乱。。。
案例数据\u属性:
//然后将当前值存储为JSON树,以便稍后对其进行反序列化
//它消耗的内存比'Cype Type属性''的情况要多,你可以认为这是最坏的情况。
final JsonElement JsonElement=gson.fromJson(in,JsonElement.class);
如果(!in.nextName().equals(TYPE_属性)){
抛出新的MalformedJsonException(“应为”+TYPE_属性+”,位于“+in”);
}
//从树中还原值
value=gson.fromJson(jsonElement,Class.forName(in.nextString());
打破
违约:
抛出新的MalformedJsonException(“无法识别的”+name+”位于“+in”);
}
if(在.hasNext()中){
抛出新的IllegalStateException(“Unexpected”+in.nextName()+”位于“+in”);
}
in.endObject();
@抑制警告(“未选中”)
最终T值=(T)值;
返回值;
}捕获(最终类NotFoundException ex){
抛出新的IOException(ex);
}
}
}
}
使用示例:

接口IWhatever{
}
final类包装器{
最终我什么都没有;
包装器(最终IwhatEvery){
这个;
}
}
final class Foo
接口信息处理器
interface IA {}

interface IR {}

class R1 implements IR {}

class R2 implements IR {}

class A1 implements IA {
    private List<IR> list;
}

class A2 implements IA {
    private A1 member;
}

class A3 implements IA {
    private A1 member;
}