2012-04-10 8 views
10

私はMappingJacksonHttpMessageConverterを通じてHibernate/Spring MVCでjackson 1.9.2を使用しています。ジャクソンは双方向の1対多の関係で混乱しています

ジャクソンは双方向の一対多の関係をシリアル化できず、無限ループになります。

私が使用しているクラスは次のとおりです。SMSインスタンスのセットを持っている

  • 会話。

  • 各SMSインスタンスはの電話番号

  • のセットがあり、それぞれのPhoneNumberは私がやろうとしていますどのような親の接触(これは双方向の多対1の関係である)

をされています会話をシリアライズする。

私は@JsonManagedReference@JsonBackReferenceを使用しない場合は、ジャクソンが原因無限ループにcrasheます。しかし、私がそれらを使用すると、の連絡先は、PhoneNumberにシリアル化されていません。電話番号

 
Class Contact { 
    @JsonManagedReference 
    List<PhoneNumber> phoneNumber ; 
} 
Class PhoneNumber { 
    @JsonBackReference 
    Contact contact; 
} 

出力である:

 
{ <--------------------- Conversation 
    "id": 51, 
    "smsSet": [ 
     { 
     "id": 53, 
     "origin":, 
     "destination": "06533844XY", 
     "message": "Hello world!", 
     "phoneNumbers": [ 
      { 
      "id": 64, 
      "num": "06533844XY", 
      "creationDate": 1333992533000, 
      } 
     ], 
     } 
    ], 
    "creationDate": 1333992534000 
    } 

代わりの最初の解決策として

 
{ <---------- conversation 
    "id": 51, 
    "smsSet": [ 
     { 
     "id": 53, 
     "origin":, 
     "destination": "06533844XY", 
     "message": "Hello world!", 
     "phoneNumbers": [ 
      { 
      "id": 64, 
      "num": "06533844XY", 
      "creationDate": 1333992533000, 
      "contact": <--------------------- Missing part 
      { 
       "id": 12, 
       "name": "Samuel Jackson", 
       "primaryNumber": "06533844XY" 
      } 
      } 
     ], 
     } 
    ], 
    "creationDate": 1333992534000 
    } 

答えて

1

、Iは、これらのアノテーションを保持し、他のクラスの作成:ContactWithouPhoneNumberをとするフィールドとして追加しましたPhoneNumberクラス。

レンダリングする前に、PhoneNumber以外のすべてのフィールドをcontactからcontactWithoutPhoneNumberにコピーします。出力JSONには、必要なものがすべて含まれています。

これはDTOデザインパターンです。

0

あなたのクラスdefに間違っているものは型なしの使用ですList;

そうでなければ、ジャクソンはデシリアライズ時の型がわからないことがあります。それを直列化しても問題が発生する可能性があります(基本型は不明です)。 だから私はまずこの問題を解決します。

さらに、あなたの依存関係が間違っている可能性があります。@JsonManagedReferenceは常に最初にシリアル化する必要があります。そうでない場合は、これらの注釈を使用することはできません。 シリアル化しようとしているオブジェクトが表示されていないと、(POJOの定義とJSONが少し外れているように)わかりにくいです。

+1

私はGenericバージョンを使用していましたが、stackoverflowエディタが<を飲み込んでいます。私は、@JsonBackReferenceが最初にシリアル化されていることが起こっていると思います。 – redochka

+0

ああ。はい、その可能性が高いです。それ以外の場合はエラーが異なります。 – StaxMan

7

私は最近、同様の問題が発生しました:ジャクソン - birectional関係を持つエンティティのシリアライズ(サイクルを避ける)

だからソリューションは、ジャクソン2.0へのアップグレード、およびクラスに次の注釈を追加することです:

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

次に、SpringがJackson 2.0で動作しないという問題があります。

<bean id="jacksonMessageConverter" 
      class="own.implementation.of.MappingJacksonHttpMessageConverter"/> 

<bean class="org.springframework.web.servlet.mvc 
      .annotation.AnnotationMethodHandlerAdapter"> 
     <property name="messageConverters"> 
      <list> 
       <ref bean="jacksonMessageConverter"/> 
      </list> 
     </property> 
     <property name="requireSession" value="false"/> 
    </bean> 

をそしてown.implementation.of.MappingJacksonHttpMessageConverterはこれに基づいている:これは、以下の方法で解決されている

http://www.jarvana.com/jarvana/view/org/springframework/spring-web/3.0.0.RELEASE/spring-web-3.0.0.RELEASE-sources.jar!/org/springframework/http/converter/json/MappingJacksonHttpMessageConverter.java?format=ok

しかし、その代わりにジャクソン2.0からObjectMapperおよびその他のジャクソンクラスを使用します*

+1

ありがとう、ちょうどこれを試して、返された会話リストの最初の会話だけで動作しているようです。何か案が? JsonIdentityInfoはどこに置くべきですか? – redochka

+0

両方のクラス(ContactとPhoneNumber)にJsonIdentityInfoを入れ、JsonBack/ManagedReference注釈を削除する必要があります(私の質問から理解している限り)。 –

+0

JsonBack/ManagedReferenceアノテーションを削除すると、次のエラーが発生します。com.fasterxml.jackson.databind.JsonMappingException:クラスcom.fasterxml.jackson.databind.deser.impl.PropertyBasedObjectIdGeneratorには、デフォルトのチェーン:java.util.ArrayList [0] - > com.model.Conversation ["smsSet"] - > java.util.LinkedHashSet [0] - > com.model.SmsBean ["phoneNumbers"] - > org.hibernate。 collection.PersistentSet [0]) – redochka

0

フィールドに@JsonIgnoreを追加すると、マッパーはシリアル化中にスキップします。それは@Transientと機能的に似ています。

これはjackson-core-aslにあります。

+2

これは実際の解決策ではありません。彼は、これらのフィールドをシリアル化する必要があります。 –

関連する問題