Gson – Custom Serialization and Deserialization

Gson offer very great features and capabilities in default serialization and deserialization. Still, we may come across the situations where default and inbuilt customization options do not solve our problems.

In this case, we can use custom serialization and deserialization using two interfaces JsonSerializer and JsonDeserializer.

1. Custom Serialization

1.1. JsonSerializer interface

The JsonSerializer interface looks like this:

public interface JsonSerializer<T> 
{
    public JsonElement serialize(T value, Type type,
        	JsonSerializationContext jsonSerializationContext) {
    }
}

After creating custom serializer for Json, we will also need to register this serializer through GsonBuilder.registerTypeAdapter(Type, Object).

Gson invokes it’s call-back method serialize() during serialization when it encounters a field of the specified type.

1.2. Gson JsonSerializer Example

Let’s say we got into situation where we have to serialize a Java object to json in such a way that all boolean values shall be written a 1 or 0 – rather printing true or false.

Let’s write the custom serializer for this requirement.

import com.google.gson.JsonElement;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;

public class BooleanSerializer implements JsonSerializer<Boolean> {

	public JsonElement serialize(Boolean aBoolean, Type type,
		JsonSerializationContext jsonSerializationContext) 
	{
		if(aBoolean){
		   return new JsonPrimitive(1);
		}
		return new JsonPrimitive(0);
	}
}

Let’s write a program to register JsonSerializer instance using registerTypeAdapter() and use it to serialize Java object to json.

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

public class Main 
{
	public static void main(String[] args) throws Exception 
	{
		Employee emp = new Employee(1, "Lokesh", "Gupta", "howtodoinjava@gmail.com", true);
		
		Gson gson = new GsonBuilder()
				.registerTypeAdapter(Boolean.class, new BooleanSerializer())
				.setPrettyPrinting()
				.create();
		
		String json = gson.toJson(emp);
		
		System.out.println(json);
	}
}

Notice the program output and value of key ‘active’ is serialized as 1.

{
  "id": 1,
  "firstName": "Lokesh",
  "lastName": "Gupta",
  "email": "howtodoinjava@gmail.com",
  "active": 1
}

2. Custom Deserialization

2.1. JsonDeserializer interface

A custom deserializer must implement the JsonDeserializer interface. The JsonDeserializer interface looks like this:

public interface JsonDeserializer<T> 
{    
	public Boolean deserialize(JsonElement jsonElement, 
	    Type type, JsonDeserializationContext jsonDeserializationContext) 
	    throws JsonParseException;
}

After creating custom deserializer for Json, we will also need to register this deserializer through GsonBuilder.registerTypeAdapter(Type, Object).

Gson invokes it’s call-back method deserialize() during serialization when it encounters a field of the specified type.

2.2. Gson JsonDeserializer Example

Let’s assume that some service returns us date field in parts i.e. day, month and year – all separately. In JSON string, they may make sense, but in Java they do not make sense until they are part of single java.time.LocalDate object.

{
  "id": 1,
  "firstName": "Lokesh",
  "lastName": "Gupta",
  "email": "howtodoinjava@gmail.com",
  "day": 11,
  "month": 8,
  "year": 2019
}

We want to to customize the deserialization and combine last three field to a LocalDate object.

Our Employee looks like this. Include necessary getters and setters, and constructors.

public class Employee 
{
	private Integer id;
    private String firstName;
    private String lastName;
    private String email;
    private LocalDate dob;
}

The custom deserializer class will look like this:

import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;

public class EmployeeDeserializer implements JsonDeserializer<Employee> 
{  
    @Override
    public Employee deserialize(JsonElement json, Type typeOfT, 
    			JsonDeserializationContext context) throws JsonParseException 
    {
        JsonObject jsonObject = json.getAsJsonObject();

        LocalDate localDate = LocalDate.of(
                jsonObject.get("year").getAsInt(),
                jsonObject.get("month").getAsInt(),
                jsonObject.get("day").getAsInt()
        );

        return new Employee(
        		jsonObject.get("id").getAsInt(), 
        		jsonObject.get("firstName").getAsString(), 
        		jsonObject.get("lastName").getAsString(), 
        		jsonObject.get("email").getAsString(), 
        		localDate);
    }
}

Let’s register the deserializer and pare the given JSON to java object.

public class Main 
{
	public static void main(String[] args) throws Exception 
	{
		String json = "{'id': 1001,"
					+ "'firstName': 'Lokesh',"
					+ "'lastName': 'Gupta',"
					+ "'email': 'howtodoinjava@gmail.com', "
					+ "'day': 11, "
					+ "'month': 8, "
					+ "'year': 2019}";
		
		Gson gson = new GsonBuilder()
				.registerTypeAdapter(Employee.class, new EmployeeDeserializer())
				.create();
		
		Employee employee = gson.fromJson(json, Employee.class);
		
		System.out.println(employee);
	}
}

Notice the program output how 3 separate fields got combined into single LocalDate object.

Employee [id=1001, 
		firstName=Lokesh, 
		lastName=Gupta, 
		email=howtodoinjava@gmail.com, 
		dob=2019-08-11]

Depending on the guarantees of the supplied json input, we might want to check with has() if the model property exists at all in the JsonObject. Otherwise we might run into NullPointerExceptions, if we’re accessing a property and then try to get a value of it.

Drop me your questions related to custom serialization and deserialization using Gson in Java.

Happy Learning !!

Leave a Reply

0 Comments
Inline Feedbacks
View all comments

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions, and frequently asked interview questions.