web-dev-qa-db-ja.com

Jackson JSONシリアル化、レベル定義による再帰回避

PojoオブジェクトをJSON表現にシリアル化するためにJacksonライブラリを使用しています。たとえば、クラスAとクラスBがあります。

class A {
  private int id;
  private B b;

  constructors...
  getters and setters
}

class B {
  private int ind;
  private A a;

  constructors...
  getters and setters
}

クラスAからオブジェクトをシリアル化する場合、シリアル化中に再帰が発生する可能性があります。 @JsonIgnoreを使用して停止できます。

深さレベルでシリアル化を制限することは可能ですか?

たとえば、レベルが2の場合、シリアル化は次のようになります。

  • シリアル化a、レベル= 0(0 <2 ok)->シリアル化
  • シリアル化a.b、レベル= 1(1 <2 ok)->シリアル化
  • a.b.aをシリアライズ、レベル= 2(2 <2は正しくない)->停止

前もって感謝します。

29
Goran Nastov

私は最近、同様の問題に遭遇しました:ジャクソン- 双方向の関係を持つエンティティのシリアル化 (サイクルの回避)

そのため、ソリューションはJackson 2.0にアップグレードし、次の注釈をクラスに追加します。

@JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class, 
                  property = "@id")
public class SomeEntityClass ...

これは完全に機能します。

22
Eugene Retunsky

次のリンクを確認してください。役立つ場合があります。

その後の唯一のオプションは、オブジェクトタイプのシリアル化/逆シリアル化用の独自のカスタムモジュールを作成することです。こちらをご覧ください:

よろしく。

13
Farid

レベルベースの無知はサポートされていません。

しかし、Jacksonに2.0での循環参照を処理させることができます。たとえば、[ Jackson 2.0 release "を使用して@JsonIdentityInfo

4
StaxMan

深さ方向のシリアル化については、こちらの例を参照してください https://github.com/abid-khan/depth-wise-json-serializer

2
Abid

自分を1レベルのみに制限する場合(つまり、現在のオブジェクトの子に移動し、それ以上移動しない場合)、@ JsonViewを使用した簡単なソリューションがあります。

別のオブジェクトへのリンクであるすべてのフィールドで、現在のクラスをビューとして注釈します:

class A {
  private int id;
  @JsonView(A.class) private B b;

  constructors...
  getters and setters
}

class B {
  private int ind;
  @JsonView(B.class) private A a;

  constructors...
  getters and setters
}

次に、シリアル化するときに、オブジェクトクラスをビューとして使用します。 Aのインスタンスをシリアル化すると、次のようになります。

{
  id: 42,
  b: {
    id: 813
  }
}

DEFAULT_VIEW_INCLUSIONがtrueに設定されていることを確認してください。設定されていない場合、@ JsonViewアノテーションのないフィールドはレンダリングされません。または、Objectクラスまたは一般的なスーパークラスを使用して、他のすべてのフィールドに@JsonViewで注釈を付けることができます。

class A {
  @JsonView(Object.class) private int id;
  @JsonView(A.class) private B b;

  constructors...
  getters and setters
}
2
Gaël Renoux

場合によっては、最大深度を保持するスレッドローカル整数を使用して、シリアル化の深度を制限できます。こちらをご覧ください answer

0
Vjeko

数か月と多くの調査を経て、私は自分のソリューションを実装して、ドメインにジャクソンの依存関係がないようにしました。

public class Parent {
    private Child child;
    public Child getChild(){return child;} 
    public void setChild(Child child){this.child=child;}
}

public class Child {
    private Parent parent;
    public Child getParent(){return parent;} 
    public void setParent(Parent parent){this.parent=parent;}
}

最初に、双方向リレーションシップの各エンティティを次のように宣言する必要があります。

public interface BidirectionalDefinition {

    @JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id", scope=Parent.class)
    public interface ParentDef{};

    @JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id", scope=Child.class)
    public interface ChildDef{};

}

その後、オブジェクトマッパーを自動的に構成できます。

ObjectMapper om = new ObjectMapper();
Class<?>[] definitions = BidirectionalDefinition.class.getDeclaredClasses();
for (Class<?> definition : definitions) {
    om.addMixInAnnotations(definition.getAnnotation(JsonIdentityInfo.class).scope(), definition);
}
0
Pablo