1. Introduction
JavaScript Object Notation (JSON) is text-based data format that is easy for humans to read and write and easy for machines to parse and generate. It is widely used for APIs to exchange data between a client and server. JSON serialization is the process of converting a Java object into a JSON string. In Java, null is a keyword that indicates the object referring to nothing. In this example, I will demonstrate JSON null serialization with both Jackson and Gson libraries. Here are main reasons to include the null values in Json serialization:
- Data Representation: including
nullvalue explicitly indicates that a value is missing or undefined, rather than omitted by mistake. - Consistent Structure: ensuring that all objects have the same structure can simplify data handling. Using
nullfor missing values can help maintain consistency. - API Communication: using
nullcan clarify that a field is intentionally left empty. This can prevent confusion about whether a field was forgotten or intentionally set to a blank state. - Database Operations: database
nullvalue can be used at queries and integrity constraints. - Schema Validation: specifying
nullcan help ensure that data conforms to the expected schema withnullvalue. - Backward Compatibility: using
nullallows new fields to be added without breaking existing systems that consume the data, as they can safely ignore or handle thenullvalues. - Default Values:
nullcan indicate a default state that needs to be populated later or a field that is optional and currently not set. - Explicit Absence: It explicitly signifies that the absence of value is acknowledged and intended, which can be important for business logic and application behavior.
2. Customer Management System
In this step, I will create a simple customer management system which has two model classes: customer and order. One customer may have one or more orders. The customer class has five fields:
id– the unique id.name– the customer’s name, this is a required field.email– the customer’s email address, it’s an optional field, but requiresnullvalue in Json serialization.custTag– the customer’s tag. it’s an optional field and only included when it’s notnull.orders– a list of orders belongs to the customer. It is an optional field.
The order class has three members:
productName– the order’s product name. It’s optional.quantity– the order’s quantity.orderTag– the optional order tag.
3. JSON Null Serialization via Jackson
The Jackson library from FasterXML is the most popular library for serializing Java objects to JSON and vice-versa. By default, it includes the null values, however, the default behavior can be overwritten with the @JsonInclude annotation and ObjectMapper.setSerializationInclusion method. In this step, I will create a maven project and demonstrate the Json null serialization via a Junit test class.
3.1 Setup Maven project
In this step, I will create a pom.xml to include the Jackson libraries.
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.zheng.demo</groupId> <artifactId>jackson-null</artifactId> <version>0.0.1-SNAPSHOT</version> <dependencies> <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.17.1</version> </dependency> <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> <version>2.17.1</version> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-api</artifactId> <version>5.10.2</version> <scope>test</scope> </dependency> </dependencies> </project>
Note: Include jackson-databind and jackson-annotations libraries.
3.2 Create Data Objects
In this step, I will create two POJO classes: Customer and Order based on the requirement at step 2.
Customer.java
package org.zheng.demo.data;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonInclude;
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Customer implements Serializable {
private static final long serialVersionUID = 5963349342478710542L;
private String custTag;
private String email;
private int id;
private String name;
private List<Order> orders;
public Customer() {
super();
}
public Customer(String name, int id) {
super();
this.id = id;
this.name = name;
}
public String getCustTag() {
return custTag;
}
public String getEmail() {
return email;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
public List<Order> getOrders() {
return orders;
}
public void setCustTag(String custTag) {
this.custTag = custTag;
}
public void setEmail(String email) {
this.email = email;
}
public void setId(int id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void addOrder(Order order) {
if (this.orders == null) {
this.orders = new ArrayList<>();
}
this.orders.add(order);
}
public void setOrders(List<Order> orders) {
this.orders = orders;
}
}
Note: line 9 marks @JsonInclude(JsonInclude.Include.NON_NULL) at the class level, so only non-null values are serialized for Customer objects.
Order.java
package org.zheng.demo.data;
import com.fasterxml.jackson.annotation.JsonInclude;
public class Order {
@JsonInclude(JsonInclude.Include.NON_NULL)
private String orderTag;
private String productName;
private int quantity;
public Order() {
super();
}
public Order(int quantity, String name) {
super();
this.quantity = quantity;
this.productName = name;
}
public String getOrderTag() {
return orderTag;
}
public String getProductName() {
return productName;
}
public int getQuantity() {
return quantity;
}
public void setOrderTag(String orderTag) {
this.orderTag = orderTag;
}
public void setProductName(String name) {
this.productName = name;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
}
Note: line 7 has @JsonInclude(JsonInclude.Include.NON_NULL) at the field level, so non-null value of the orderTag field is included when serializing the Order objects.
3.3 Test via Jackson ObjectMapper
In this step, I will create a JacksonTest class which has five test methods.
test_include_null_as_default– print out theOrder‘s JSON string and verify that Jackson libraryObjectMapperincludesnullvalues in JSON as default.test_include_null_as_default_with_exclusion– similar totest_include_null_as_default, but theorderTagfield overrides the default setting with@JsonInclude(JsonInclude.Include.NON_NULL.test_setSerializationInclusion_for_nonNull– verify the default includesnullvalues overwritten by theObjectMapper.setSerializationInclusion(Include.NON_NULL);test_annotation_for_nonNull– TheCustomerclass declares@JsonInclude(JsonInclude.Include.NON_NULL)at class level, sonullvalues are excluded from JSON serialization.test_mixed_annotation– verify the mixed@JsonInclude(JsonInclude.Include.NON_NULL)atCustomerclass declaration and theOrder‘s field declaration.
JacksonTest.java
package org.zheng.demo;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.jupiter.api.Test;
import org.zheng.demo.data.Customer;
import org.zheng.demo.data.Order;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
class JacksonTest {
private Customer cust = new Customer("Zheng", 30);
private ObjectMapper ob = new ObjectMapper();
private Order order = new Order();
@Test
void test_annotation_for_nonNull() {
cust.setEmail("test@test.com");
String jsonStr;
try {
jsonStr = ob.writerWithDefaultPrettyPrinter().writeValueAsString(cust);
assertFalse(jsonStr.contains("null"),
"Json string contains non-null due to JsonInclude.Include.NON_NULL set at class level.");
System.out.println(jsonStr);
Customer person2 = ob.readValue(jsonStr, Customer.class);
assertEquals("Zheng", person2.getName());
assertEquals(30, person2.getId());
assertEquals("test@test.com", person2.getEmail());
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}
@Test
void test_include_null_as_default() {
String jsonStr;
try {
jsonStr = ob.writeValueAsString(order);
assertTrue(jsonStr.contains("null"), "Json string contains null by Jackson default");
assertFalse(jsonStr.contains("custTag"),
"set JsonInclude.Include.NON_NULL on the custTag, so won't include");
// include null element
System.out.println(jsonStr); // {"productName":null,"quantity":0}
Order data = ob.readValue(jsonStr, Order.class);
assertNull(data.getOrderTag());
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}
@Test
void test_include_null_as_default_with_exclusion() {
order.setOrderTag("serialize if not null");
String jsonStr;
try {
jsonStr = ob.writeValueAsString(order);
assertTrue(jsonStr.contains("null"), "Json string contains null by Jackson default");
assertTrue(jsonStr.contains("orderTag"),
"set JsonInclude.Include.NON_NULL on the orderTag. include as it has value.");
// include null element
System.out.println(jsonStr);
// {"orderTag":"serialize if not null","productName":null,"quantity":0}
Order data = ob.readValue(jsonStr, Order.class);
assertEquals("serialize if not null", data.getOrderTag());
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}
@Test
void test_mixed_annotation() {
cust.addOrder(order);
String jsonStr;
try {
jsonStr = ob.writerWithDefaultPrettyPrinter().writeValueAsString(cust);
assertFalse(jsonStr.contains("\"email\" : null"),
"Json string contains non-null due to JsonInclude.Include.NON_NULL set at Customer class level.");
assertTrue(jsonStr.contains("\"productName\" : null"),
"Json string contains non-null due to JsonInclude.Include.NON_NULL set at Customer class level.");
System.out.println(jsonStr);
Customer person2 = ob.readValue(jsonStr, Customer.class);
assertEquals("Zheng", person2.getName());
assertEquals(30, person2.getId());
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}
@Test
void test_setSerializationInclusion_for_nonNull() {
String jsonStr;
try {
ob.setSerializationInclusion(Include.NON_NULL);
jsonStr = ob.writeValueAsString(order);
assertFalse(jsonStr.contains("null"),
"Json string contains non-null when setSerializationInclusion() is configured globally");
// only include non-null element
System.out.println(jsonStr);// {"quantity":0}
Order data = ob.readValue(jsonStr, Order.class);
assertNull(data.getOrderTag());
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}
}
- Line 17 – creates and initializes a
custobject from theCustomerclass. - Line18 – creates an
ObjectMapperwith default setting. - Line 19 – creates and initializes an
orderobject from theOrderclass. - Line 27 – serializes the
custobject into Json viawriteValueAsStringwith default pretty format. - Line 47 – serializes the
orderobject into Json viawriteValueAsString. - Line 69 – Excludes the “
orderTag” field as it marks with@JsonInclude(JsonInclude.Include.NON_NULL). - Line 122 – overwrites the
ObjectMappersetting withob.setSerializationInclusion(Include.NON_NULL);
3.4 Demonstrate Json Null Serialization via Jackson
In this step, I will execute each test method and capture the output.
test_annotation_for_nonNull output
{
"email" : "test@test.com",
"id" : 30,
"name" : "Zheng"
}
Note: serialized the non-null values as the Customer class annotated with @JsonInclude(JsonInclude.Include.NON_NULL).
test_include_null_as_default output
{"productName":null,"quantity":0}Note: the productName is included with null value but the orderTag is excluded due to @JsonInclude(JsonInclude.Include.NON_NULL) annotation.
test_include_null_as_default_with_exclusion output
{"orderTag":"serialize if not null","productName":null,"quantity":0}
Note: the productName is included with null value and the orderTag is included as it is not null.
test_mixed_annotation output
{
"id" : 30,
"name" : "Zheng",
"orders" : [ {
"productName" : null,
"quantity" : 0
} ]
}
Note: the order’s productName is included with null value. but the email is excluded due to @JsonInclude(JsonInclude.Include.NON_NULL) at the Customer class level.
test_setSerializationInclusion_for_nonNull output
{"quantity":0}Note: non-null values are serialized due to ob.setSerializationInclusion(Include.NON_NULL).
4. JSON Null Serialization via Gson
Gson is a Java library from Google that serializes and deserializes Java Objects into their JSON representation and vice-versa. By default, Gson does not include any null values in the JSON. I will demonstrate how to include Null values via GsonBuilder().serializeNulls().
4.1 Setup Maven project
In this step, I will create a pom.xml to include the Gson library.
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.zheng.demo</groupId> <artifactId>gson-null</artifactId> <version>0.0.1-SNAPSHOT</version> <dependencies> <!-- https://mvnrepository.com/artifact/com.google.code.gson/gson --> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.11.0</version> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-api</artifactId> <version>5.10.2</version> <scope>test</scope> </dependency> </dependencies> </project>
4.2 Create Data Objects
This step is similar to step 3.2 but with Gson’s @Expose annotation which marks fields intended to expose so we can use excludeFieldsWithoutExposeAnnotation to customize JSON fields.
Customer.java
package org.zheng.demo.data;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import com.google.gson.annotations.Expose;
public class Customer implements Serializable {
private static final long serialVersionUID = 5963349342478710542L;
private String custTag;
@Expose
private String email;
@Expose
private int id;
@Expose
private String name;
private List<Order> orders;
public Customer() {
super();
}
public Customer(String name, int id) {
super();
this.id = id;
this.name = name;
}
public void addOrder(Order order) {
if (orders == null) {
orders = new ArrayList<>();
}
orders.add(order);
}
public String getCustTag() {
return custTag;
}
public String getEmail() {
return email;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
public List<Order> getOrders() {
return orders;
}
public void setCustTag(String custTag) {
this.custTag = custTag;
}
public void setEmail(String email) {
this.email = email;
}
public void setId(int id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setOrders(List<Order> orders) {
this.orders = orders;
}
}
Note: line 15, 18 21 annotate @Expose so these fields will be serialized when excludeFieldsWithoutExposeAnnotation is configured.
The Order class detail.
Order.java
package org.zheng.demo.data;
public class Order {
private String productName;
private int quantity;
public Order() {
super();
}
public Order(int quantity, String productName) {
super();
this.quantity = quantity;
this.productName = productName;
}
public String getProductName() {
return productName;
}
public int getQuantity() {
return quantity;
}
public void setProductName(String productName) {
this.productName = productName;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
}
4.3 Create Gson Test
In this step, I will create a GsonTest class with six methods to demonstrate Json null serialization via Gson and GsonBuilder libraries.
test_default_nonnull– theGsonandGsonBuilder'sexcludenullvalues as default.test_serializeNulls– verifynullvalues are serialized whenserializeNullsis used.test_serialize_null_with_Expose– verify null values are serialized whenserializeNullsmethod is used and excludes these fields not marked with the@Exposeannotation.
GsonTest.java
package org.zheng.demo;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.jupiter.api.Test;
import org.zheng.demo.data.Customer;
import org.zheng.demo.data.Order;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
class GsonTest {
private Customer customer = new Customer("Mary", 5);
private Order order = new Order(1, null);
@Test
void test_default_nonnull() {
// By default, Gson excludes fields with null values.
String json = new Gson().toJson(order);
assertFalse(json.contains("null"), "Gson default excludes null values.");
System.out.println(json); // {"quantity":1}
// using the GsonBuilder and setting the serializeNulls method.
String jsonString = new GsonBuilder().create().toJson(customer);
assertFalse(jsonString.contains("null"), "GsonBuilder default excludes null values.");
System.out.println(jsonString); // {"id":5,"name":"Mary"}
}
@Test
void test_serialize_null_with_Expose() {
Gson gson = new GsonBuilder().serializeNulls().excludeFieldsWithoutExposeAnnotation().create();
customer.setCustTag("NOT_Serialized_field");
String jsonStr = gson.toJson(customer);
assertFalse(jsonStr.contains("notIncludeInJson"), "not expose field not included");
assertTrue(jsonStr.contains("null"), "Json string contains null when serializeNulls() is configured");
System.out.println(jsonStr);
// {"email":null,"id":5,"name":"Mary"}
Customer desObj = gson.fromJson(jsonStr, Customer.class);
assertNull(desObj.getCustTag());
}
@Test
void test_serializeNulls() {
customer.addOrder(order);
Gson gson = new GsonBuilder().serializeNulls().create();
String jsonString = gson.toJson(customer);
assertTrue(jsonString.contains("custTag"),
"not calling excludeFieldsWithoutExposeAnnotation, so ignore the @expose.");
assertTrue(jsonString.contains("null"), "Json string contains null when serializeNulls() is configured");
System.out.println(jsonString);
// {"custTag":null,"email":null,"id":5,"name":"Mary","orders":[{"productName":null,"quantity":1}]}
}
}
- Line 16, 17 – defined a
customerandorderobjects. - Line 20 – verify the
Gsondefault setting includes non-null values. - Line 22 –
toJson()serializes a Java object into JSON string. - Line 36, 37 – verify the
GsonBuilderwithserializeNullsandexcludeFieldsWithoutExposeAnnotation() which includes nulls but excludes the fields without@Exposeannotation. - Line 54, 57 – verify the
GsonBuilderwithserializeNulls() to serialize null values.
4.4 Demonstrate Json Null Serialization via Gson
In this step, I will execute each test and capture the output.
test_default_nonnull output
{"quantity":1}
{"id":5,"name":"Mary"}
Note: by Gson default, only non-null values are serialized.
test_serialize_null_with_Expose output
{"email":null,"id":5,"name":"Mary"}
Note: the email with the null value is serialized as expected.
test_serializeNulls output
{"custTag":null,"email":null,"id":5,"name":"Mary","orders":[{"productName":null,"quantity":1}]}
Note: the null email from customer and null productName from order are serialized as expected.
5. Conclusion
Serializing JSON with null values provides clarity and consistency. In this example, I demonstrated how to serialize JSON with null values with both Jackson and Gson open source libraries. The following table outlines the main difference at Null serialization between these two popular libraries.
| Jackson | Gson | |
| Open-source | active development | maintenance mode, no new features |
| Default null setting | include null values as default | exclude null values as default |
| Configuration | setSerializationInclusion | serializeNulls |
| Annotation | @JsonInclude(JsonInclude.Include.NON_NULL) | No |
6. Download
These were two examples of maven projects which utilize both Jackson and Gson libraries for JSON null values serialization.
You can download the full source code of this example here: Include null Value in JSON Serialization
Thank you!
We will contact you soon.

This site uses Akismet to reduce spam. Learn how your comment data is processed.