2012-04-10 106 views
10

我使用傑克遜1.9.2與Hibernate/Spring MVC通過MappingJacksonHttpMessageConverter。傑克遜混淆雙向一對多關係

傑克遜無法序列化雙向一對多關係,並造成無限循環。

我使用的類是:

  • 對話具有設置短信實例。

  • 每個SMS實例都有一套PHONENUMBERS

  • 每******中國有一個父接觸(這是雙向的多對一的關係)

我所試圖做的是序列化對話。

如果我不使用@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

作爲第一解決方案,我保持在這些註釋和創​​建的其他類:ContactWithouPhoneNumber並添加它作爲一個字段PhoneNumber類。

現在,在渲染之前,我複製除PhoneNumber之外的所有字段,從聯繫人到contactWithoutPhoneNumber。輸出JSON包含我需要的所有東西。

這是DTO設計模式。

0

你的班裏有一件事是錯誤的def是使用無類型List;你應該有:

List<PhoneNumber> phoneNumber ; 

因爲否則傑克遜無法知道反序列化時的類型是什麼;甚至在序列化時可能會導致問題(因爲基本類型不確定)。 所以我會先解決這個問題。

但另外你的依賴可能是錯誤的方式:@JsonManagedReference必須始終是序列化的第一件事。如果情況並非如此,則不能使用這些註釋。 沒有看到你想要序列化的對象,很難確切知道(POJO定義和JSON看起來稍微偏離)。

+1

我使用的是通用版本,stackoverflow編輯器吞噬了<。我認爲發生的事情是@JsonBackReference首先被序列化。 – redochka 2012-04-11 21:31:30

+0

好的。是的,這似乎更可能;否則錯誤將會不同。 – StaxMan 2012-04-11 23:11:42

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

但使用ObjectMapper和其他類傑克遜來自傑克遜的2.0,而不是of Jackson 1. *

+1

謝謝,剛剛嘗試過這一點,它似乎只處理返回的對話列表中的第一個對話。任何想法?我應該在哪裏放JsonIdentityInfo? – redochka 2012-04-17 12:22:07

+0

您需要爲這兩個類(Contact和PhoneNumber)添加JsonIdentityInfo並刪除JsonBack/ManagedReference註釋(據我所知,您的問題)。 – 2012-04-17 14:14:14

+0

當我刪除JsonBack/ManagedReference註解時,出現以下錯誤:com.fasterxml.jackson.databind.JsonMappingException:類com.fasterxml.jackson.databind.deser.impl.PropertyBasedObjectIdGenerator沒有默認(無arg)構造函數(通過引用鏈:java.util.ArrayList [0] - > com.model.Conversation [「smsSet」] - > java.util.LinkedHashSet [0] - > com.model.SmsBean [「phoneNumbers」] - > org.hibernate。 collection.PersistentSet [0]) – redochka 2012-04-21 20:15:39

0

您可以將@JsonIgnore添加到字段,映射器將在序列化期間跳過它們。它在功能上類似於@Transient。

它在jackson-core-asl中。

+2

這不是一個真正的解決方案。他需要這些字段被序列化。 – 2013-06-05 18:15:38