0

私はJavaオブジェクトを持っています。他のさまざまな種類の Java オブジェクトへの参照、場合によってはそれ自体への参照を持つ多数のフィールドがあります。このオブジェクトは、双方向の参照 (またはサイクル) を持つマップ (またはグラフ) として最もよく説明できます。その構造を分析する権限はありませんが、問題を解決するには、このグラフをシリアル化し、JSON 文字列に格納する必要があります。

ライブラリクラスを使用してオブジェクトの構造を実際に見ることができないという事実は、私の唯一のオプションです(私が考える限り)。json-io、json-lib、google genson、gson、flexjson を試しました。しかし、これらのライブラリはすべて、サイクルが存在するためにスタックして例外をスローするか、json を返すことができます (json-io のみがこれを行います) が、多くの重要なフィールドがスキップされます (遅延ロードされるもの)。 、およびゲッターが必要です)。

質問: 私の問題に対処するためだけに上記のライブラリをテストしているときに、見落としている可能性のあるものはありますか?

私が持っている Java オブジェクトは非常に複雑ですが、Facebook のような大きな Web サイトで使用される可能性のあるオブジェクトほど複雑になるとは思いません。私の問題に対処するために使用できるいくつかの主要なライブラリとその特定の構成は何ですか?

4

1 に答える 1

0

あなたにとって最良の選択肢はJackson Streaming APIだと思います。これにより、オブジェクト グラフをテラバースしながら POJO を json にシリアライズできるため、シリアライズ プロセスの制御を維持し、循環参照やその他の特殊なケースを検出して処理できます。

編集:循環参照を処理する例を実装しようとしましたが、完了できませんでした。ここに私の中間結果があります:

  1. デフォルトを呼び出すObjectMapper.WriteValue(...)と、次の例外が発生しますcom.fasterxml.jackson.databind.JsonMappingException: Direct self-reference leading to cycle。これは、Jackson が自己参照のケースを検出できることを意味します。デフォルトのデリアライザーは、このケースを処理する方法を知りません。
  2. 例外をスローするデフォルトの動作は、これがいつ設定されるかを指定することでオフにできますmapper.configure(SerializationFeature.FAIL_ON_SELF_REFERENCES, false);。デフォルトのデリアライザーはスタック オーバーフローを引き起こします。そのため、自己参照を検出して処理するカスタム シリアライザーを実装する必要があります。
  3. 次のことを行うカスタムシリアライザーを作成しようとしました: a) 自己参照を検出します。b) 見つかった場合は、参照を示すために何かを印刷します。c) そうでない場合は、デフォルトのシリアル化を行います。しかし、「デフォルトのシリアル化」の呼び出し方がわかりませんでした。私の中間ソリューションを以下に示します。

自己参照を持つことができるクラスの例:

public class Node {
    public String name = "";
    public Node child = null;

    public Node(String name) { this.name = name; }

    public String getname()        { return name; }
    public Node   getChild()       { return child; }
    public void   setChild(Node n) { child = n; }
}

カスタムシリアライザ

public class NodeJsonSerializer extends JsonSerializer<Node> {
    // list so we can detect multiple cases of self references
    static List<Node> alreadySerializedNodes = new ArrayList<>();

    @Override
    public void serialize(Node n, JsonGenerator gen, SerializerProvider serializers) 
            throws IOException, JsonProcessingException {
        for (Node alreadySerialized : alreadySerializedNodes) {
            // do not invoke equals() since you want to find duplicate references 
            if (alreadySerialized == n) {
                // mark this as self reference 
                gen.writeStartObject();
                gen.writeStringField("node-ref", alreadySerialized.getname());
                gen.writeEndObject();
                return;
            }
        }
        alreadySerializedNodes.add(n);

        // default derialization ...
        gen.writeStartObject();
        gen.writeStringField("name", n.getname());
        gen.writeObjectField("child", n.getChild());
        gen.writeEndObject();
    }
}

呼び出し:

Node n1 = new Node("n1");
n1.setChild(n1);  // self referencing

ObjectMapper mapper = new ObjectMapper();
// registering custom serializer is through module 
SimpleModule sm = new SimpleModule("MyModule");
sm.addSerializer(Node.class, new NodeJsonSerializer());
// making sure default serializer ignores self referencing is through module mapper.configure(SerializationFeature.FAIL_ON_SELF_REFERENCES, false);
mapper.registerModule(sm);

System.out.println(mapper.writeValueAsString(n1));

出力は{"name":"n1","child":{"node-ref":"n1"}}

于 2015-06-07T06:46:28.283 に答える