web-dev-qa-db-ja.com

JsonとJava-循環参照

私は循環参照を持っていて、問題を抱えています。

オブジェクトをフロントエンドに返すRestWebサービスがあります。問題は、複数の参照を持つオブジェクトを返そうとすると、無限の応答が返され、生成されます。

Java.lang.IllegalStateException: 
    Cannot call sendError() after the response has been committed

オブジェクトはHibernateコード生成によって自動的に生成され、バックエンドに循環参照が必要です。Jacksonを使用してフロントエンドに情報を送信する前に、循環参照を削除する必要があります。

コントローラメソッドのヘッダーは次のとおりです。

@RequestMapping(value="/list", method=RequestMethod.POST)
public @ResponseBody eventResponse list(@RequestBody String sessionID) {

私はJsonに変換するために明示的に何もしていません。私はこれを初めて使用し、jacksonがこれを自動的に解決したと思います。

18
Faabass

これについては2つの方法があります。エンティティを外部に公開する必要がある場合は、循環参照の原因となっているプロパティに @JsonIgnore を追加することをお勧めします。これにより、Jacksonはそのプロパティをシリアル化しないようになります。

もう1つの方法は、Jacksonが提供する双方向機能を使用することです。 @JsonManagedReference または @JsonBackReference のいずれかを使用できます。 @JsonManagedReferenceはプロパティの「転送」部分であり、通常どおりシリアル化されます。 @JsonBackReferenceは参照の「後ろ」の部分です。シリアル化されませんが、「フォワード」タイプが逆シリアル化されると再構築されます。

あなたは例をチェックすることができます ここ

これはあなたのコメントに対処します:この場合あなたがしたいと思うかもしれないことは外の世界に見えるDTOを使うことだと思います。エンティティを外部に公開したくないので、このアプローチが好きです。これは、JacksonアノテーションがエンティティではなくDTOにあることを意味します。エンティティをDTOに変換するある種のマッパーまたはコンバーターが必要になります。これで、エンティティに変更を加えても、マッパー/コンバーターを変更しない限り、DTOに伝達されません。エンティティに変更を加えるときに、その変更を公開するかどうかを決定できるため、これは問題ないと思います。

[〜#〜]更新[〜#〜]

ジャクソンで双方向の関係を処理するさまざまな方法について詳しく説明している優れたブログ投稿 ここ があります。 @JsonIgnore@JsonManagedReference@JsonBackReference@JsonIdentityInfo@JsonView、およびカスタムシリアライザーを使用するソリューションについても説明します。これは、使用できるさまざまなテクニックのかなり包括的な記述です。

34
Vivin Paliath

単一の注釈@JsonIdentityInfo問題を解決します。循環参照も処理します。 参照

8
pavan

@JsonbTransientは、循環参照を処理するために私の問題を解決しました。

@JsonbTransient // javax.json.bind.annotation.JsonbTransient
@ManyToOne
@JoinColumn(name = "userId", referencedColumnName = "id", nullable = false)
public AContainedEntity getAContainedEntity() {
       return aContainedEntity;
}
0
Csongi77