Jackson Custom Serializer

By Arvind Rai, 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.

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();
   }
} 
We have created custom serializer 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 with ObjectMapper, 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); 
We will get following output.
{
  "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); 
Output will be as following.
{
  "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. 
The output will be as following.
{
  "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(); 
The output will be as following.
{
  "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(); 
Find the output.
{
  "writerName" : "Mr. Mohit",
  "favPageGroups" : [ [ 10, 30, 35, 50 ], [ 5, 15, 25, 45 ] ]
} 

Custom Serializer for Object

In our Writer class we have an object property.
@JsonProperty("writerAddress")
private Address address; 
We can custom serialize it as following.
gen.writeObjectFieldStart("writerAddress");
gen.writeStringField("city", writer.getAddress().getCity().toUpperCase());
gen.writeStringField("country", writer.getAddress().getCountry().toUpperCase());
gen.writeEndObject(); 
Find the output.
  "writerAddress" : {
    "city" : "NOIDA",
    "country" : "INDIA"
  } 

Custom Serializer for List

In our Writer class we have a List type property as following.
@JsonProperty("allBooks")	
private List<Book> allBookList; 
We can custom serialize it as following.
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(); 
Find the output.
  "allBooks" : [ {
    "bookName" : "Learning-Java",
    "bookCategory" : "Java"
  }, {
    "bookName" : "Learning-Hibernate",
    "bookCategory" : "Hibernate"
  } ] 

Custom Serializer for Map

In our Writer class we have a Map type property as following.
@JsonProperty("favBooks")	
private Map<String, Book> favBookMap; 
We can custom serialize it as following.
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(); 
Find the output.
  "favBooks" : {
    "B202" : {
      "bookName" : "Learning-Hibernate",
      "bookCategory" : "Hibernate"
    },
    "A101" : {
      "bookName" : "Learning-Java",
      "bookCategory" : "Java"
    }
  } 

Complete Example

build.gradle
apply 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'
} 
WriterCustomSerializer.java
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();
	}
} 
Address.java
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;
  }
} 
Book.java
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;
	}
} 
Writer.java
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;
	}
} 
To use @JsonSerialize, we need to annotate it at Writer class level as given below.
@JsonSerialize(using= WriterCustomSerializer.class)
public class Writer {
    ------
} 
In that case we need not to register our 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);
  }
} 
Output
{
  "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 StdSerializer
Jackson @JsonSerialize Annotation

Download Source Code

POSTED BY
ARVIND RAI
ARVIND RAI
LEARN MORE








©2024 concretepage.com | Privacy Policy | Contact Us