Jackson Custom Serializer
April 05, 2018
This page will walk through Jackson custom serializer example. To create a custom serializer, we need to create a class by extending Jackson StdSerializer
class and override its serialize
method. Jackson JsonGenerator
provides the methods to write JSON values, start and end markers for JSON object and array with required white spaces if pretty printing is enabled. To use our custom serializer, either we need to register it with ObjectMapper
or use @JsonSerialize
annotation at class level that needs to be serialized. On this page we will provide how to serialize the properties of a class that is an object, list, map and array. Now we will discuss complete example step by step.
Contents
- Technologies Used
- StdSerializer
- Custom Serializer with ObjectMapper
- Custom Serializer with @JsonSerialize Annotation
- JsonGenerator writeStartObject() and writeEndObject()
- JsonGenerator writeObjectFieldStart()
- JsonGenerator writeArrayFieldStart(), writeArray() and writeEndArray()
- Custom Serializer for Object
- Custom Serializer for List
- Custom Serializer for Map
- Complete Example
- References
- Download Source Code
Technologies Used
Find the technologies being used in our example.1. Java 9
2. Jackson 2.9.4
3. Gradle 4.3.1
4. Eclipse Oxygen
StdSerializer
StdSerializer
is used for custom serializers and is used by all standard serializers, too. StdSerializer
is abstract class and extends JsonSerializer
. To create a custom serializer, we need to create a class by extending StdSerializer
and override serialize
method.
WriterCustomSerializer.java
public class WriterCustomSerializer extends StdSerializer<Writer> { private static final long serialVersionUID = 1L; public WriterCustomSerializer() { this(Writer.class); } protected WriterCustomSerializer(Class<Writer> t) { super(t); } @Override public void serialize(Writer writer, JsonGenerator gen, SerializerProvider provider) throws IOException { gen.writeStartObject(); gen.writeStringField("writerName", "Mr. "+ w.getName()); gen.writeEndObject(); } }
WriterCustomSerializer
for our Writer
class. Find the structure of Writer
class.
Writer.java
public class Writer { @JsonProperty("writerName") private String name; @JsonProperty("writerAddress") private Address address; @JsonProperty("allBooks") private List<Book> allBookList; @JsonProperty("favBooks") private Map<String, Book> favBookMap; ------ }
Custom Serializer with ObjectMapper
To use our custom serializer withObjectMapper
, we need to register our custom serializer with ObjectMapper
using SimpleModule
as following.
ObjectMapper mapper = new ObjectMapper(); SimpleModule module = new SimpleModule(); module.addSerializer(new WriterCustomSerializer()); mapper.registerModule(module);
SimpleModule
is used to register serializers and deserializers. To register a serializer we need to call its addSerializer
method. To register a deserializer, we need to call addDeserializer
method.
Now we can serialize object of our
Writer
class as given below.
Writer writer = new Writer("Mohit", book, address); String jsonWriter = mapper.writerWithDefaultPrettyPrinter() .writeValueAsString(writer);
{ "writerName" : "Mr. Mohit" }
Custom Serializer with @JsonSerialize Annotation
We can configure our custom serializer with@JsonSerialize
annotating at value class, field or getter method level. When we annotate at value class, configuration is used for instances of the value class. We will annotate our Writer
class with @JsonSerialize
as following.
Writer.java
@JsonSerialize(using= WriterCustomSerializer.class) public class Writer { @JsonProperty("writerName") private String name; @JsonProperty("writerAddress") private Address address; @JsonProperty("allBooks") private List<Book> allBookList; @JsonProperty("favBooks") private Map<String, Book> favBookMap; ------ }
using
metadata is used to assign custom serializer. @JsonSerialize
has other metadata such as as
, typing
etc.
Now serialize
Writer
as given below.
ObjectMapper mapper = new ObjectMapper(); String jsonWriter = mapper.writerWithDefaultPrettyPrinter() .writeValueAsString(writer); System.out.println(jsonWriter);
{ "writerName" : "Mr. Mohit" }
JsonGenerator writeStartObject() and writeEndObject()
writeStartObject(): It writes starting marker of JSON object value i.e. { and it also provides required white spaces if pretty printing is enabled.writeEndObject(): It writes closing marker JSON object value i.e. } and it also provides required white spaces if pretty printing is enabled.
writeStringField(): It outputs a field entry that has a string value. We need to pass field name and value.
Find the sample code.
gen.writeStartObject(); gen.writeStringField("writerName", "Mr. "+ w.getName()); gen.writeEndObject(); Serialization output with pretty printing.
{ "writerName" : "Mr. Mohit" }
JsonGenerator writeObjectFieldStart()
writeObjectFieldStart()
writes a field entry that itself has JSON object value. It also writes START_OBJECT marker i.e. { . To close it we need to call writeEndObject()
method.
gen.writeStartObject(); gen.writeStringField("writerName", "Mr. "+ w.getName()); gen.writeObjectFieldStart("writerBook"); gen.writeStringField("bookName", w.getBook().getName().replace(" ", "-")); gen.writeStringField("bookCategory", w.getBook().getCategory()); gen.writeEndObject(); gen.writeEndObject();
{ "writerName" : "Mr. Mohit", "writerBook" : { "bookName" : "Learning-Java", "bookCategory" : "Java" } }
JsonGenerator writeArrayFieldStart(), writeArray() and writeEndArray()
writeArrayFieldStart(): It writes JSON array and START_ARRAY marker i.e. [ and it also writes required white spaces if pretty printing is enabled.writeArray(): It writes a single array.
writeEndArray(): It writes closing JSON array marker i.e. ] and it also writes required white spaces if pretty printing is enabled.
Find the sample code.
gen.writeStartObject(); gen.writeStringField("writerName", "Mr. "+ w.getName()); gen.writeArrayFieldStart("favPageGroups"); int[] group1 = {10, 30, 35, 50}; int[] group2 = {5, 15, 25, 45}; gen.writeArray(group1, 0, 4); gen.writeArray(group2, 0, 4); gen.writeEndArray(); gen.writeEndObject();
{ "writerName" : "Mr. Mohit", "favPageGroups" : [ [ 10, 30, 35, 50 ], [ 5, 15, 25, 45 ] ] }
Custom Serializer for Object
In ourWriter
class we have an object property.
@JsonProperty("writerAddress") private Address address;
gen.writeObjectFieldStart("writerAddress"); gen.writeStringField("city", writer.getAddress().getCity().toUpperCase()); gen.writeStringField("country", writer.getAddress().getCountry().toUpperCase()); gen.writeEndObject();
"writerAddress" : { "city" : "NOIDA", "country" : "INDIA" }
Custom Serializer for List
In ourWriter
class we have a List
type property as following.
@JsonProperty("allBooks") private List<Book> allBookList;
gen.writeArrayFieldStart("allBooks"); for(Book book: writer.getAllBookList()) { gen.writeStartObject(); gen.writeStringField("bookName", book.getName().replace(" ", "-")); gen.writeStringField("bookCategory", book.getCategory()); gen.writeEndObject(); } gen.writeEndArray();
"allBooks" : [ { "bookName" : "Learning-Java", "bookCategory" : "Java" }, { "bookName" : "Learning-Hibernate", "bookCategory" : "Hibernate" } ]
Custom Serializer for Map
In ourWriter
class we have a Map
type property as following.
@JsonProperty("favBooks") private Map<String, Book> favBookMap;
gen.writeObjectFieldStart("favBooks"); for(Map.Entry<String, Book> entry : writer.getFavBookMap().entrySet()){ gen.writeObjectFieldStart(entry.getKey()); gen.writeStringField("bookName", entry.getValue().getName().replace(" ", "-")); gen.writeStringField("bookCategory", entry.getValue().getCategory()); gen.writeEndObject(); } gen.writeEndObject();
"favBooks" : { "B202" : { "bookName" : "Learning-Hibernate", "bookCategory" : "Hibernate" }, "A101" : { "bookName" : "Learning-Java", "bookCategory" : "Java" } }
Complete Example
build.gradleapply plugin: 'java' apply plugin: 'eclipse' archivesBaseName = 'concretepage' version = '1' repositories { mavenCentral() } dependencies { compile group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: '2.9.4' compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.9.4' compile group: 'com.fasterxml.jackson.core', name: 'jackson-annotations', version: '2.9.4' }
package com.concretepage; import java.io.IOException; import java.util.Map; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.ser.std.StdSerializer; public class WriterCustomSerializer extends StdSerializer<Writer> { private static final long serialVersionUID = 1L; public WriterCustomSerializer() { this(Writer.class); } protected WriterCustomSerializer(Class<Writer> t) { super(t); } @Override public void serialize(Writer writer, JsonGenerator gen, SerializerProvider provider) throws IOException { gen.writeStartObject(); //Write property gen.writeStringField("writerName", "Mr. "+ writer.getName()); //Write Address object gen.writeObjectFieldStart("writerAddress"); gen.writeStringField("city", writer.getAddress().getCity().toUpperCase()); gen.writeStringField("country", writer.getAddress().getCountry().toUpperCase()); gen.writeEndObject(); //Iterate List gen.writeArrayFieldStart("allBooks"); for(Book book: writer.getAllBookList()) { gen.writeStartObject(); gen.writeStringField("bookName", book.getName().replace(" ", "-")); gen.writeStringField("bookCategory", book.getCategory()); gen.writeEndObject(); } gen.writeEndArray(); //Iterate Map gen.writeObjectFieldStart("favBooks"); for(Map.Entry<String, Book> entry : writer.getFavBookMap().entrySet()){ gen.writeObjectFieldStart(entry.getKey()); gen.writeStringField("bookName", entry.getValue().getName().replace(" ", "-")); gen.writeStringField("bookCategory", entry.getValue().getCategory()); gen.writeEndObject(); } gen.writeEndObject(); gen.writeEndObject(); } }
package com.concretepage; import com.fasterxml.jackson.annotation.JsonProperty; public class Address { @JsonProperty("city") private String city; @JsonProperty("country") private String country; public Address() {} public Address(String city, String country) { this.city = city; this.country = country; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } public String getCountry() { return country; } public void setCountry(String country) { this.country = country; } }
package com.concretepage; import com.fasterxml.jackson.annotation.JsonProperty; public class Book { @JsonProperty("bookName") private String name; @JsonProperty("bookCategory") private String category; public Book(){} public Book(String name, String category) { this.name = name; this.category = category; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getCategory() { return category; } public void setCategory(String category) { this.category = category; } }
package com.concretepage; import java.util.List; import java.util.Map; import com.fasterxml.jackson.annotation.JsonProperty; public class Writer { @JsonProperty("writerName") private String name; @JsonProperty("writerAddress") private Address address; @JsonProperty("allBooks") private List<Book> allBookList; @JsonProperty("favBooks") private Map<String, Book> favBookMap; public Writer(){} public Writer(String name, Address address, List<Book> allBookList, Map<String, Book> favBookMap){ this.name = name; this.address = address; this.allBookList = allBookList; this.favBookMap = favBookMap; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } public List<Book> getAllBookList() { return allBookList; } public void setAllBookList(List<Book> allBookList) { this.allBookList = allBookList; } public Map<String, Book> getFavBookMap() { return favBookMap; } public void setFavBookMap(Map<String, Book> favBookMap) { this.favBookMap = favBookMap; } }
@JsonSerialize
, we need to annotate it at Writer
class level as given below.
@JsonSerialize(using= WriterCustomSerializer.class) public class Writer { ------ }
WriterCustomSerializer
with ObjectMapper
.
Here we are running the example registering
WriterCustomSerializer
with ObjectMapper
.
ObjectToJSON.java
package com.concretepage; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.module.SimpleModule; public class ObjectToJSON { public static void main(String[] args) throws JsonProcessingException { Address address = new Address("Noida", "India"); Book book1 = new Book("Learning Java", "Java"); Book book2 = new Book("Learning Hibernate", "Hibernate"); Book book3 = new Book("Learning Spring", "Spring"); List<Book> allBookList = Arrays.asList(book1, book2, book3); Map<String, Book> favBookMap = new HashMap<>(); favBookMap.put("A101", book1); favBookMap.put("B202", book2); Writer writer = new Writer("Mohit", address, allBookList, favBookMap); ObjectMapper mapper = new ObjectMapper(); SimpleModule module = new SimpleModule(); module.addSerializer(new WriterCustomSerializer()); mapper.registerModule(module); String jsonWriter = mapper.writerWithDefaultPrettyPrinter() .writeValueAsString(writer); System.out.println(jsonWriter); } }
{ "writerName" : "Mr. Mohit", "writerAddress" : { "city" : "NOIDA", "country" : "INDIA" }, "allBooks" : [ { "bookName" : "Learning-Java", "bookCategory" : "Java" }, { "bookName" : "Learning-Hibernate", "bookCategory" : "Hibernate" }, { "bookName" : "Learning-Spring", "bookCategory" : "Spring" } ], "favBooks" : { "B202" : { "bookName" : "Learning-Hibernate", "bookCategory" : "Hibernate" }, "A101" : { "bookName" : "Learning-Java", "bookCategory" : "Java" } } }
References
Jackson StdSerializerJackson @JsonSerialize Annotation