GSON 不会反序列化对外部类的引用 [英] GSON does not deserialize reference to outer class

查看:27
本文介绍了GSON 不会反序列化对外部类的引用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的 Java 应用程序中,我定义了两个类,分别称为 AB,其中 BA 的内部类代码>.两者都定义为可序列化

On my Java application, I defined two classes, called A and B where B is inner class of A. Both are defined as serializable

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.

Before serializing this object with GSON, getSomeCalculationValue works fine. But, after serializing and deserializing, getSomeCalculationValue fails with a NullPointerException.

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

This happens because the inner class B doesn´t have a reference to outer class A anymore, so, A.this fails.

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

Does anybody knows how could I solve this, that is restoring the inner to outer reference while deserializing this object?

推荐答案

正如 Gson 文档所说:

As Gson documentation says:

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

Gson can serialize static nested classes quite easily.

Gson 还可以反序列化静态嵌套类.但是,Gson 可以不会自动反序列化纯内部类,因为它们无参数构造函数也需要对包含对象的引用这在反序列化时不可用.你可以通过使内部类静态或通过为其提供自定义 InstanceCreator.

Gson can also deserialize static nested classes. However, Gson can not automatically deserialize the pure inner classes since their no-args constructor also need a reference to the containing Object which is not available at the time of deserialization. You can address this problem by either making the inner class static or by providing a custom InstanceCreator for it.

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

Changing B to a static inner class is not possible since your method needs a reference to the outer class in getSomeCalculationValue, so, I've tried to solve your problem with an InstanceCreator but solution was a bit ugly, so I propose you to use a custom deserialized. I changed your A class a little, making items public to make easier to create the example I show you.

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;
    }

}

这就是我使用它的方式:

And this is how I use it:

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. 我的反序列化器缺少空案例管理,你应该完成空JSON或空字段.
  1. You do not need to implement Serializable interface, JSON has nothing in common with Java serialization
  2. My deserializer lacks of null cases management, you should complete for null JSON or null fields.

这篇关于GSON 不会反序列化对外部类的引用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆