Enable Javascript

Please enable Javascript to view website properly

Toll Free 1800 889 7020

Looking for an Expert Development Team? Take 2 weeks Free Trial! Try Now

Spring Custom Serializers with @JsonIdentityInfo

Technology: Jackson-databind is one of the libraries widely used in modern spring-based applications for serialization or deserialization from/to JSON. Jackson library will convert the object to JSON, and vice versa.

If the object is complex and needs to customize the serialization/ deserialization then we need to write Custom Serializer which extends default Jackson provided serializer i.e. com.fasterxml.jackson.databind.ser.std.StdSerializer.

Defining Custom Serializer: We will create StudentCustomSerializer class to customize the Student class, it must extend.

spring-custom-serializers-with-@jsonidentityinfo

com.fasterxml.jackson.databind.ser.std.StdSerializer and create required constructor methods and default constructor with no-arguments.

We need to implement one abstract serialize method, how to want to serialize the object.

public class StudentSerializer extends StdSerializer<Student> { private static final long serialVersionUID = 1L; public StudentSerializer() { this(null); } protected StudentSerializer(Class<Student> t) { super(t); } @Override public void serialize(Student student, JsonGenerator gen, SerializerProvider provider) throws IOException { gen.writeStartObject(); provider.defaultSerializeField("id", student.getId(), gen); provider.defaultSerializeField("name_custom", student.getName(), gen); provider.defaultSerializeField("name_custom", student.getEmail(), gen); gen.writeEndObject(); } }

And Student class look like below:

@JsonSerialize(using = StudentSerializer.class) public class Student { private Long id; private String name; private String email; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } }

Here we are criticizing the student class with the sonJsonSerialize annotation and passing the above custom serializer class to use the attribute so that it will be called during the serializing.

If we run and our main class will look like below:

public class Main { public static void main(String[] args) throws Exception { final Student student = new Student(); student.setId(1 L); student.setEmail("student@gmail.com"); student.setName("s1"); final ObjectMapper mapper = new ObjectMapper(); final String json = mapper.writeValueAsString(student); System.out.println(json); } }

If we run the program output will look like below:

{"id":1,"name_custom":"s1","name_custom":"[email protected]"}

Circular References:

Create course POJO type class and add the List in student class.

Create student variables in Courses class, so that it will maintain one-to-many relations.

Student.java

public class Student { private Long id; private String name; private String email; private List<Course> courses = new ArrayList<>(); // getters and setters } public class Course { private Long id; private String name; private Student student; //getters and setters }

If we serialize the student class using object mapper, as a student depends on Course, Course will depend on Student Serialization. We can observe a cycle, java will throw StackOverflow exception, and to overcome this circular Reference, Jackson library provides new annotation @JsonIdentityInfo.

Add the below line at the class level of the student so that from the 2nd time onwards it will serialize the only id property instead of the whole object.

@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")

After adding student class look like below:

@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id") public class Student { private Long id; private String name; private String email; private List<Course> courses = new ArrayList<>(); //getters and setters }

main class :

public static void main(String[] args) throws Exception { final Student student = new Student(); student.setId(1 L); student.setEmail("student@gmail.com"); student.setName("s1"); final Course course1 = new Course(); course1.setId(1 L); course1.setName("course1"); course1.setStudent(student); final Course course2 = new Course(); course2.setId(2 L); course2.setName("course2"); course2.setStudent(student); final List < Course> courses = new ArrayList <> (); courses.add(course1); courses.add(course2); student.setCourses(courses); final ObjectMapper mapper = new ObjectMapper(); final String json = mapper.writeValueAsString(student); System.out.println(json); } }

If we run without @JsonIdentityInfo annotation, we can observe the below error in the console.

jsonidentityinfo-annotation

If we run with annotation, we can see the serialized student output:

{"id":1,"name":"s1","email":"student@gmail.com","courses":[{"id":1,"name":"course1","student":1},{"id":2,"name":"course2","student":1}]}

Now we can observe course class will only contain student IDs, other fields are skipped.

Custom Serializer AutoWired Problem:

If we would like @autowired some of the bean into our custom serializer, by default not possible, as the custom serializer is not of spring bean type.

ObjectMapper provides one to way injects using objectInstantiator, spring extends this objectInstantiator to autowire the beans inside the custom serializer class using the below code.

ObjectMapper mapper = Jackson2ObjectMapperBuilder.json().build();

mapper.setHandlerInstantiator(new SpringHandlerInstantiator(this.applicationContext.getAutowireCapableBeanFactory()));

This we can inject spring beans into a custom serializer, and we can override the serialize according to our needs.

Conclusion: Jackson is one of the libraries to used serializes the object from/to JSON in Java application development, it provides a useful annotation to avoid Circular reference.

Jackson library also provides the way to customize the serialization, and also we saw how to inject spring beans into a custom serializer using HandlerInstantiator.

Software Development Team
Need Software Development Team?
captcha
🙌

Thank you!
We will contact soon.

Oops! Something went wrong.

Recent Blogs

Categories

NSS Note
Trusted by Global Clients