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
}
}
}
_
どうやってやるの?
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
によってルートオブジェクトを参照しています。
この循環参照または無限再帰の問題を解決するには、いくつかのアプローチがあります。これは link それぞれを詳細に説明しています。各関連エンティティの上の@JsonIdentityInfoアノテーションを含む問題を解決しましたが、@ JsonViewはより最近のものであり、あなたのシーナリーによってはより良いソリューションになるかもしれません。
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
または、IntSequenceGenerator実装を使用します。
@JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class)
@Entity
public class A implements Serializable
...