Jackson BiDirectional relationship the right way (Preventing infinite recursion exception with Java Jackson)

 

Probably you might have come to this post, because you are doing some REST based application development. You might have come across the issue of infinite recursion with Jackson JSON parser. I am using this post to show you some jackson JSON example on how to solve this issue. I created this post on the issue and scenario what I faced during development.

I am using two classes. “User” and “Role” which has a one-to-many relationship.

Class User and Role

User.javaRole.java

The “User” class

The “Role” class

To demonstrate the issue I am using the following to rest method using Spring MVC Rest Controller.

REST method for “Get User List”

REST method for “Get Role List”

 

The problem with the above model is, it would create a recursion in the relationship of both entities (User and Role) and it will never end. This leads to the following error.

There are different types of solutions for this issue depending on the situation and the resulting model what we expect. In any solutions, it is expected to break the chain in one of the objects so that recursion will stop going deep.

Let us look at a scenario using @JsonIgnore annotation. It is just a matter of adding annotation @JsonIgnoreat one side of the relation. In our case let’s add it to the class Role and look at the results.

Adding the annotation @JsonIgnore in class Role for the property users.

After executing, the result as follow.

Get User List

Get Role List

This is pretty fine in grabbing the list of users. But if we need to grab the list of roles, we are missing the users associated with the roles in the result.

The @JsonManagedReference and @JsonBackReference

The next solution is using the annotation @JsonManagedReference and the @JsonBackReference. @JsonManagedReference is the forward part of the relation and the @JsonBackReference is the back part of the relation. The recursion chain will be broken in this part. Also using the above case, the result is similar as @JsonIgnore using our objects.

Using the JsonManageReference in class User

Using the JsonBackReference in class Role

The @JsonIdentityInfo

Another useful annotation is, @JsonIdentityInfo. This is a bit different idea. With this annotation, everytime jackson serialize your object, it will add an ID or an attribute of your choice to the object. So that it will not entirely scan the relation which is scanned already.

Adding JsonIdentityInfor to class User

Adding JsonIdentityInfo to class Role

In our case, it won’t help. To understand why is it, I will produce the result below.

Get User List

Get Role List

The above result describes well why is this not suitable for our scenario. It has its own place where it can be used perfectly.

Thinking about a quick solution..!

I was having the similar issue when I was coming across the same kind of relationship between my classes. It did not help me using three of those annotation methods. The other two are @JsonView and custom serialization classes. I did not prefer writing another class when my objective is just to serialize. Eventually, I use some other workaround that could break the recursion loop and could satisfy my both REST path and produce the intended result.

First thing, remove any special jackson annotation what we added above. then,

Modify the REST method for “Get User List”

Modify the REST method for “Get Role List”

This way I could easily get the result what I wished. The resulting JSON arrays are below.

Get User List

Get Role List

Finally, I have my resulting records as per my need. If you are willing to work with Custom serialization class, this is a good link to follow with “Jackson – Custom Serializer“. I believe it could help others. If you have any comment and concerns feel free to write below.

Leave a Reply

Your email address will not be published. Required fields are marked *


*

Please wrap all source codes with [code][/code] tags.