2012-04-10 63 views
10

Tôi đang sử dụng jackson 1.9.2 với Hibernate/Spring MVC thông qua MappingJacksonHttpMessageConverter.Jackson nhầm lẫn với mối quan hệ một-hai chiều hai chiều

Jackson không thể tuần tự hóa mối quan hệ một-nhiều chiều hai chiều và tạo vòng lặp vô hạn.

Các lớp tôi đang sử dụng là:

  • thoại trong đó có một Set các trường hợp tin nhắn SMS.

  • Mỗi trường hợp tin nhắn SMS có Set của PHONENUMBERS

  • Mỗi PhoneNumber có một số liên lạc cha mẹ (đây là hai chiều đến nhiều-một mối quan hệ)

Những gì tôi đang cố gắng làm là để sắp xếp một cuộc hội thoại.

Nếu tôi không sử dụng @JsonManagedReference@JsonBackReference sau đó jackson sẽ crashe do một vòng lặp vô hạn. Nhưng khi tôi sử dụng chúng, Liên hệ không được đăng theo thứ tự thành PhoneNumber.

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

Đầu ra là:

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

thay vì

 
{ <---------- 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 
    } 

Trả lời

1

Là một giải pháp đầu tiên, tôi vẫn tiếp tục các chú thích và tạo ra một lớp khác: ContactWithouPhoneNumber và thêm nó như là một lĩnh vực để lớp PhoneNumber.

Bây giờ, trước khi hiển thị, tôi sao chép tất cả các trường trừ PhoneNumber, từ liên hệ sang số liên lạcWithoutPhoneNumber. JSON đầu ra chứa mọi thứ tôi cần.

Đây là mẫu thiết kế DTO.

0

Một điều sai trong lớp học của bạn là sử dụng untyped List; bạn nên có:

List<PhoneNumber> phoneNumber ; 

vì nếu không Jackson không thể biết loại nào là khi deserializing; và thậm chí trên serializing nó có thể gây ra vấn đề (như là loại cơ sở là không biết chắc chắn). Vì vậy, trước tiên tôi sẽ khắc phục sự cố này.

Nhưng bổ sung phụ thuộc của bạn có thể sai cách xung quanh: @JsonManagedReference PHẢI luôn là điều đầu tiên để tuần tự hóa. Nếu đây không phải là trường hợp, bạn không thể sử dụng các chú thích này. Nếu không thấy các đối tượng bạn đang cố gắng sắp xếp, khó có thể biết chắc chắn (định nghĩa POJO và JSON có vẻ hơi tắt).

+1

Tôi đang sử dụng phiên bản Chung, trình chỉnh sửa stackoverflow đã nuốt <. Tôi nghĩ rằng những gì đang xảy ra là @JsonBackReference đang được tuần tự hóa đầu tiên. – redochka

+0

Ah ok. Vâng, điều đó dường như có nhiều khả năng hơn; lỗi sẽ khác đi. – StaxMan

7

Gần đây tôi đã gặp phải một vấn đề tương tự: Jackson - serialization của đơn vị với các mối quan hệ birectional (tránh chu kỳ)

Vì vậy, giải pháp là nâng cấp lên Jackson 2.0, và thêm vào các lớp học chú thích sau:

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

Sau đó, vấn đề là Spring không hoạt động với Jackson 2.0. Điều này đã được giải quyết theo cách sau:

<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> 

Và own.implementation.of.MappingJacksonHttpMessageConverter được dựa trên này:

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

Nhưng sử dụng ObjectMapper và các lớp Jackson khác từ Jackson 2.0 thay vì của Jackson 1. *

+1

Cảm ơn, Chỉ cần thử điều này và có vẻ như chỉ hoạt động với Cuộc trò chuyện đầu tiên trong Danh sách cuộc trò chuyện đã trả về. Bất kỳ ý tưởng? Tôi nên đặt JsonIdentityInfo ở đâu? – redochka

+0

Bạn cần phải đặt JsonIdentityInfo cho cả hai lớp (Contact và PhoneNumber) và loại bỏ chú thích JsonBack/ManagedReference (theo như tôi hiểu từ câu hỏi của bạn). –

+0

Khi tôi xóa chú thích JsonBack/ManagedReference tôi nhận được lỗi sau: com.fasterxml.jackson.databind.JsonMappingException: Lớp com.fasterxml.jackson.databind.deser.impl.PropertyBasedObjectIdGenerator không có hàm tạo mặc định (no arg) (thông qua tham chiếu chuỗi: java.util.ArrayList [0] -> com.model.Conversation ["smsSet"] ​​-> java.util.LinkedHashSet [0] -> com.model.SmsBean ["phoneNumbers"] -> org.hibernate. collection.PersistentSet [0]) – redochka

0

Bạn có thể thêm @JsonIgnore vào trường và trình ánh xạ sẽ bỏ qua chúng trong quá trình tuần tự hóa. Nó tương tự như hàm @Transient.

Nó nằm trong jackson-core-asl.

+2

Đây không thực sự là một giải pháp . Anh ta cần những lĩnh vực đó để được sắp xếp theo thứ tự. –

Các vấn đề liên quan