Java
JSON
jpa
JavaEE

[Java] エンティティのJSON化において、無限ループを防ぐ

More than 1 year has passed since last update.

概要

エンティティAとBの2つがあります。

AとBは双方向にリレーションシップをはっています。

ここでAをJSONシリアライズすると……

Aをシリアライズ

AからリレーションシップをたどってBもシリアライズ

BからリレーションシップをたどってAをシリアライズ




(以下続く)

というように、無限ループになってしまいます。これを防ぐ方法です。

方法1:シリアライズを一方向に制限する

リレーションシップは双方向のままで、シリアライズのみを一方向にできます。

AをシリアライズしたときはBもシリアライズします。けど、BをシリアライズしたときはAをシリアライズしません。

方法は、A側に@JsonManagedReferenceアノテーションをつけ、B側に@JsonBackReferenceをつけます。

A.java
@Entity
class A implements Serializable {
   @OneToMany(mappedBy="a")
   @JsonManagedReference
   private List<B> bList;
}
B.java
@Entity
class B implements Serializable {
   @ManyToOne
   @JsonBackReference
   private A a;
}

Aをシリアライズすると、このようになります。

{
  b: [
    { }
  ]
}

方法2:複数回登場するエンティティは、IDに置き換える

エンティティクラスに@JsonIdentityInfoをつけると、シリアライズ時にIDを発行し、同じエンティティを参照するときはIDに置き換わります。

A.java
@Entity
@JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class)
class A implement Serializable {
   @OneToMany(mappedBy="a")
   private List<B> bList;
}
B.java
@Entity
class B implements Serializable {
   @ManyToOne
   private A a;
}

Aをシリアライズすると、このようになります。

{
  @Id: 1
  b: [
    { a: 1 }  /* @Id=1のオブジェクトを参照している */
  ]
}