web-dev-qa-db-ja.com

循環参照で@JsonIdentityInfoを使用する方法は?

here のように、Jackson 2の@JsonIdentityInfoを使用しようとしています。

テストのために、次の2つのクラスを作成しました。

_public class A
{
    private B b;
    // constructor(s) and getter/setter omitted
}
public class B
{
    private A a;
    // see above
}
_

もちろん、単純なアプローチは失敗します。

_@Test
public void testJacksonJr() throws Exception
{
    A a = new A();
    B b = new B(a);
    a.setB(b);
    String s = JSON.std.asString(a);// throws StackOverflowError
    Assert.assertEquals("{\"@id\":1,\"b\":{\"@id\":2,\"a\":1}}", s);
}
_

@JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="@id")をクラスAおよび/またはクラスBに追加しても機能しません。

私はaを次のようなものにシリアライズ(および後でデシリアライズ)できることを望んでいました(ただし、JSONについてはあまりわかりません)。

_{
    "b": {
        "@id": 1,
        "a": {
            "@id": 2,
            "b": 1
        }
    }
}
_

どうやってやるの?

8
Burkhard

jackson-jr にはJacksonの機能のサブセットがあるようです。 @JsonIdentityInfoはカットしてはいけません。

Jacksonライブラリ全体を使用できる場合は、質問で提案した@JsonIdentityInfoアノテーションを付けた標準のObjectMapperを使用し、オブジェクトをシリアル化します。例えば

@JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="@id")
public class A {/* all that good stuff */}

@JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="@id")
public class B {/* all that good stuff */}

その後

A a = new A();
B b = new B(a);
a.setB(b);
ObjectMapper mapper = new ObjectMapper();
System.out.println(mapper.writeValueAsString(a));

生成します

{
    "@id": 1,
    "b": {
        "@id": 2,
        "a": 1
    }
}

ここで、ネストされたaは、その@idによってルートオブジェクトを参照しています。

17

この循環参照または無限再帰の問題を解決するには、いくつかのアプローチがあります。これは link それぞれを詳細に説明しています。各関連エンティティの上の@JsonIdentityInfoアノテーションを含む問題を解決しましたが、@ JsonViewはより最近のものであり、あなたのシーナリーによってはより良いソリューションになるかもしれません。

@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")

または、IntSequenceGenerator実装を使用します。

@JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class)
@Entity
public class A implements Serializable 
...
0
Cassio Seffrin