Gson和抽象超类:反序列化问题

11
假设有一个抽象类,比如说 A,还有两个非抽象的子类,分别是A1A2。我想使用GSON库将它们从json格式中“反序列化”出来。
例如,我得到了一个A对象的数组。
int n = ...;
A[] list = new A[n];
A[0] = new A1(....);
A[1] = new A2(....);
...

有人将其转换为JSON字符串如下:

String json = (new Gson()).toJson(list);

最后,如果我尝试按以下方式反序列化

A[] deserializedList =  (new Gson()).fromJson(json, A[].class);

然后我遇到了一个错误,因为GSON默认的反序列化程序找到了一个抽象类(即A),但它无法猜测子类类型。

我该如何解决这个问题?

PS:我读过自定义反序列化程序,但我不知道在这种情况下要如何使用它们。


7
请看这个链接http://ovaraksin.blogspot.com.es/2011/05/json-with-gson-and-abstract-classes.html。该文章介绍了如何使用GSON和抽象类处理JSON数据。 - Axxiss
2
@Axxiss 哦!好的,所以我不能使用简单列表,我必须在序列化字符串中保存对象类类型。嗯!如果GSON的开发人员能够添加一种方法来启用自动保存类类型属性,那就更好了! - mat_boy
1
好的,请回答与这个问题相关的内容,这样我就可以接受它了! - mat_boy
目前我没有时间给出更好的答案。也许你应该以这个链接为起点自己创建一个答案;) - Axxiss
1
当然,我会这样做的。我的目标是接受你的答案,为你颁发积分! - mat_boy
尝试使用显式类名像 A[] deserializedList = (new Gson()).fromJson(json, A1.class) 这样的语法,你有没有遇到任何错误?@mat_boy - MaheshVarma
1个回答

19

根据Axxiss的链接,下面是答案。必须提供一个自定义的序列化器/反序列化器。

public class AClassAdapter  implements JsonSerializer<A>, JsonDeserializer<A> {
  @Override
  public JsonElement serialize(A src, Type typeOfSrc, JsonSerializationContext context) {
      JsonObject result = new JsonObject();
      result.add("type", new JsonPrimitive(src.getClass().getSimpleName()));
      result.add("properties", context.serialize(src, src.getClass())); 
      return result;
  }


  @Override
  public A deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
        throws JsonParseException {
    JsonObject jsonObject = json.getAsJsonObject();
    String type = jsonObject.get("type").getAsString();
    JsonElement element = jsonObject.get("properties");

    try {            
        String fullName = typeOfT.getTypeName();
        String packageText = fullName.substring(0, fullName.lastIndexOf(".") + 1);

        return context.deserialize(element, Class.forName(packageText + type));
    } catch (ClassNotFoundException cnfe) {
        throw new JsonParseException("Unknown element type: " + type, cnfe);
    }
  }
}

然后进行序列化,步骤如下:

GsonBuilder gson = new GsonBuilder();
gson.registerTypeAdapter(A.class, new ATypeAdapter());
String json = gson.create().toJson(list);

而根据给定的JSON字符串,反序列化过程如下:

GsonBuilder gson = new GsonBuilder();
gson.registerTypeAdapter(A.class, new ATypeAdapter());

return gson.create().fromJson(json, A[].class);

4
为客户完美地工作了。不错。 - Donn Felker

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