GSON没有反序列化对外层的引用

时间:2013-10-18 12:31:58

标签: java json serialization deserialization gson

在我的Java应用程序中,我定义了两个类,名为AB,其中BA的内部类。两者都被定义为可序列化

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失败。

有人知道我怎么能解决这个问题,那就是在反序列化这个对象时恢复内部到外部引用?

1 个答案:

答案 0 :(得分:6)

正如Gson的文档所说:

  

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

     

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

将B更改为静态内部类是不可能的,因为您的方法需要引用getSomeCalculationValue中的外部类,所以,我试图用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 JSON或null字段。