如何使用Gson反序列化接口类型?

4
我有一个接口。
public interace ABC {
}

实现方法如下:
public class XYZ implements ABC {
    private Map<String, String> mapValue;
    public void setMapValue( Map<String, String> mapValue) {
        this.mapValue = mapValue;
    }  

    public  Map<String, String> getMapValue() {
        return this.mapValue
    }
}

我想使用Gson反序列化一个类,它的实现如下:
public class UVW {
    ABC abcObject;
}

当我尝试像这样反序列化它:gson.fromJson(jsonString, UVW.class); 它会返回null。jsonString是UTF_8字符串。
这是因为UVW类中使用了接口吗?如果是,那么我该如何反序列化这样的类呢?

仅给定类型为 ABC 的字段,Gson 如何知道如何反序列化 JSON? - Sotirios Delimanolis
如何让Gson知道使用ABC的XYZ实现? - AFH
@SotiriosDelimanolis那个问题已经过时了。他建议使用RuntimeTypeAdapterFactory,而这个现在已经在代码库中了(他说没有),然后建议使用JsonDeserializer,但这基本上已经被弃用了。 - durron597
如果你愿意,你可以提供一个更新的答案。不需要在问题之间分散回答。 - Sotirios Delimanolis
@durron597 我不介意重新打开(你也可以),我只是不想答案到处都是。有很多帖子解释如何解决这个问题。 - Sotirios Delimanolis
显示剩余2条评论
1个回答

5
你需要告诉Gson在反序列化ABC时使用XYZ。你可以使用TypeAdapterFactory来实现这一点。 简而言之:
public class ABCAdapterFactory implements TypeAdapterFactory {
  private final Class<? extends ABC> implementationClass;

  public ABCAdapterFactory(Class<? extends ABC> implementationClass) {
     this.implementationClass = implementationClass;
  }

  @SuppressWarnings("unchecked")
  @Override
  public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
    if (!ABC.class.equals(type.getRawType())) return null;

    return (TypeAdapter<T>) gson.getAdapter(implementationClass);
  }
}

这是一个完整的工作测试框架,用于说明此示例:
public class TypeAdapterFactoryExample {
  public static interface ABC {

  }

  public static class XYZ implements ABC {
    public String test = "hello";
  }

  public static class Foo {
    ABC something;
  }

  public static void main(String... args) {
    GsonBuilder builder = new GsonBuilder();
    builder.registerTypeAdapterFactory(new ABCAdapterFactory(XYZ.class));
    Gson g = builder.create();

    Foo foo = new Foo();
    foo.something = new XYZ();

    String json = g.toJson(foo);
    System.out.println(json);
    Foo f = g.fromJson(json, Foo.class);
    System.out.println(f.something.getClass());
  }
}

输出:

{"something":{"test":"hello"}}
class gson.TypeAdapterFactoryExample$XYZ

如果你只有一个子类型,那么这很简单。在这种情况下,你不需要为目标类型添加任何提示。但是如果再添加另一个子类型,就会变得更加复杂。 - Sotirios Delimanolis
如果我有一个XYZ< T >类,我该如何实现? - vishal patel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接