Reputation: 12839
I'm using jackson 1.9.2 with Hibernate/Spring MVC through MappingJacksonHttpMessageConverter.
Jackson can not serialize bidirectional one-to-many relationship and makes an infinite loop.
The classes I'm using are :
Conversation which has a Set of SMS instances.
Each SMS instance has a Set of PhoneNumbers
Each PhoneNumber has a parent contact (this is the bidirectional many-to-one relationship)
What I am trying to do is to serialize a conversation.
If I don't use @JsonManagedReference and @JsonBackReference then jackson will crashe due to an infinite loop. But when I use them, the Contact doesn't get serialized into the PhoneNumber.
Class Contact { @JsonManagedReference List<PhoneNumber> phoneNumber ; } Class PhoneNumber { @JsonBackReference Contact contact; }
The output is :
{ <--------------------- Conversation "id": 51, "smsSet": [ { "id": 53, "origin": 0123465, "destination": "06533844XY", "message": "Hello world!", "phoneNumbers": [ { "id": 64, "num": "06533844XY", "creationDate": 1333992533000, } ], } ], "creationDate": 1333992534000 }
instead of
{ <---------- conversation "id": 51, "smsSet": [ { "id": 53, "origin": 0123465, "destination": "06533844XY", "message": "Hello world!", "phoneNumbers": [ { "id": 64, "num": "06533844XY", "creationDate": 1333992533000, "contact": <--------------------- Missing part { "id": 12, "name": "Samuel Jackson", "primaryNumber": "06533844XY" } } ], } ], "creationDate": 1333992534000 }
Upvotes: 11
Views: 14050
Reputation: 12839
As a first solution, I kept these annotations and created an other class: ContactWithouPhoneNumber and added it as a field to the PhoneNumber class.
Now, before rendering, I copy all fields except PhoneNumber, from contact to contactWithoutPhoneNumber. The output JSON contains every thing I need.
This is the DTO design pattern.
Upvotes: 2
Reputation: 31
You can add @JsonIgnore to fields and the mapper will skip over them during serialization. It is similar in function to @Transient.
It is in the jackson-core-asl.
Upvotes: 0
Reputation: 13139
I recently encountered a similar problem: Jackson - serialization of entities with birectional relationships (avoiding cycles)
So the solution is to upgrade to Jackson 2.0, and add to classes the following annotation:
@JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class,
property = "@id")
public class SomeEntityClass ...
Then the problem is that Spring doesn't work with Jackson 2.0. This has been solved in the following way:
<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>
And the own.implementation.of.MappingJacksonHttpMessageConverter is based on this:
But use ObjectMapper
and other Jackson classes from Jackson 2.0 instead of Jackson 1.*
Upvotes: 7
Reputation: 116590
One thing wrong in your class def is use of untyped List
; you should rather have:
List<PhoneNumber> phoneNumber ;
since otherwise Jackson can not know what the type is when deserializing; and even on serializing it could cause problems (as base type is not known for sure). So I would first fix this issue.
But additionally your dependency may be wrong way around: @JsonManagedReference
MUST always be the first thing to serialize. If this is not the case, you can not use these annotations.
Without seeing objects you are trying to serialize it is hard to know for sure (POJO definition and JSON seem slightly off).
Upvotes: 0