6

私の Java アプリケーションでは、 という 2 つのクラスを定義しました。ABwhereBは の内部クラスですA。どちらもシリアライズ可能として定義されています

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 は純粋な内部クラスを自動的に逆シリアル化することはできません。引数のないコンストラクターは、逆シリアル化の時点では利用できない包含オブジェクトへの参照も必要とするためです。この問題は、内部クラスを静的にするか、カスタム InstanceCreator を提供することで解決できます。

getSomeCalculationValueあなたのメソッドは の外部クラスへの参照を必要とするため、 B を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

最後に 2 つの注意事項:

  1. インターフェースを実装する必要はありませんSerializable。JSON は Java シリアライゼーションと共通点はありません。
  2. 私のデシリアライザーには null ケース管理がありません。null JSON または null フィールドを完了する必要があります。
于 2013-10-18T21:51:31.050 に答える