6

在我的 Java 应用程序中,我定义了两个类,A称为. 两者都定义为可序列化BBA

public class A implements Serializable {

    int attrParent;
    List<B> items = new ArrayList<B>();

    public void setAttrParent(int attrParent) {
        this.attrParent = attrParent;
    }

    public int getAttrParent() {
        return attrParent;
    }

    public class B implements Serializable {

        private int attr;

        public void setAttr(int attr) {
            this.attr = attr;
        }

        public int getAttr() {
            return attr;
        }

        public int getSomeCalculationValue() {
            return this.attr * A.this.attrParent; // Problems occurs here
        }

    }
}

使用 GSON 序列化此对象之前,getSomeCalculationValue工作正常。但是,序列化和反序列化之后,getSomeCalculationValue失败并带有NullPointerException.

发生这种情况是因为内部B类不再引用外部类A,因此A.this失败。

有谁知道我该如何解决这个问题,即在反序列化这个对象的同时恢复内部到外部的引用?

4

1 回答 1

7

正如 Gson 文档所说:

Gson 可以很容易地序列化静态嵌套类。

Gson 还可以反序列化静态嵌套类。但是,Gson 不能自动反序列化纯内部类,因为它们的无参数构造函数还需要对包含 Object 的引用,而在反序列化时这是不可用的。您可以通过将内部类设为静态或为其提供自定义 InstanceCreator 来解决此问题。

将 B 更改为静态内部类是不可能的,因为您的方法需要引用外部类 in getSomeCalculationValue,所以,我尝试用 an 解决您的问题,InstanceCreator但解决方案有点难看,所以我建议您使用自定义反序列化. A我稍微更改了您的课程,将项目公开,以便更轻松地创建我向您展示的示例。

public class ADeserializer implements JsonDeserializer<A> {
    public A deserialize(JsonElement json, Type typeOfT,
        JsonDeserializationContext context) throws JsonParseException {

    A a = new A();
    a.attrParent = json.getAsJsonObject().get("attrParent").getAsInt();
    JsonArray ja = json.getAsJsonObject().get("items").getAsJsonArray();
    for(JsonElement e: ja){
        B b = a.new B();
        b.setAttr(e.getAsJsonObject().get("attr").getAsInt());
        a.items.add(b);
    }
    return a;
    }

}

这就是我使用它的方式:

public class Q19449761 {

    public static void main(String[] args) {

        A a = new A();
        a.setAttrParent(3);
        B b = a.new B();
        b.setAttr(10);
        a.items.add(b);
        System.out.println("Before serializing: "  + a.items.get(0).getSomeCalculationValue());

        Gson g = new Gson();

        String json = g.toJson(a, A.class);
        System.out.println("JSON string: " + json);

        A test2 = g.fromJson(json, A.class);

        try {
            System.out.println("After standard deserialization: " +test2.items.get(0).getSomeCalculationValue());
        } catch (Exception e) {
            e.printStackTrace();
        }

        GsonBuilder builder = new GsonBuilder();
        builder.registerTypeAdapter(A.class, new ADeserializer());

        A test3 = builder.create().fromJson(json, A.class);

        System.out.println("After custom deserialization: " + test3.items.get(0).getSomeCalculationValue());

    }

}

这是我的执行:

Before serializing: 30
JSON string: {"attrParent":3,"items":[{"attr":10}]}
java.lang.NullPointerException
    at stackoverflow.questions.q19449761.A$B.getSomeCalculationValue(A.java:32)
    at stackoverflow.questions.q19449761.Q19449761.main(Q19449761.java:26)
After custom deserialization: 30

最后的两个注意事项:

  1. 不需要实现Serializable接口,JSON 和 Java 序列化没什么共同点
  2. 我的反序列化器缺少 null 案例管理,您应该完成 null JSON 或 null 字段。
于 2013-10-18T21:51:31.050 回答