As a part of End to End REST Assured Tutorial, in this post, We will learn about an important annotation @JsonInclude of Jackson library which helps in eliminating default, null, empty, etc values. For this post, we will focus on excluding null and empty values in a payload.
Maven Dependency
Since we are going to use an annotation provided by Jackson API, we need to add the Jackson library in our project. I am using maven as a build tool here.
Always try to use the latest dependency from the Central Maven Repository. I will use the below dependency at the time of writing this post.
com.fasterxml.jackson.core jackson-databind 2.11.1
We have already learned about @JsonInclude annotation and different values of Include enum in the previous post.
Usage of NON_NULL
In Java, a default value is provided to class variables. A chart is below:-
Data Type | Default Value (for fields) |
---|---|
byte | 0 |
short | 0 |
int | 0 |
long | 0L |
float | 0.0f |
double | 0.0d |
char | ‘u0000’ |
String (or any object) | null |
boolean | false |
The most dangerous default value is NULL. If we do not put checks or validation of null values we may end up with NullPointerException. Sometimes ignoring all default values is not good and we just want to ignore NULL values. In that case, we can use NON_NULL of Include enum as shown below:-
package JacksonTutorials; import com.fasterxml.jackson.annotation.JsonInclude; @JsonInclude(JsonInclude.Include.NON_NULL) public class Employee { // private variables or data members of pojo class private String firstName; private String lastName; private String gender; private int age; private double salary; private boolean married; // Getter and setter methods public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public double getSalary() { return salary; } public void setSalary(double salary) { this.salary = salary; } public boolean getMarried() { return married; } public void setMarried(boolean married) { this.married = married; } }
Converting Java Object to JSON Object
package JacksonTutorials; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; public class AnnotationJsonIncludeExample { public static void main(String[] args) throws JsonProcessingException { // Just create an object of Pojo class Employee employee = new Employee(); // Set value as you wish employee.setFirstName("Amod"); employee.setMarried(true); // Converting a Java class object to a JSON payload as string ObjectMapper objectMapper = new ObjectMapper(); String employeeJson = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(employee); System.out.println(employeeJson); } }
Output
{ "firstName" : "Amod", "age" : 0, "salary" : 0.0, "married" : true }
We have not set values for fields ‘lastName’, ‘gender’,’age’ and ‘salary’. Since default values of fields ‘lastName’ and ‘gender’ are NULL which will be ignored during serialization but default values of fields ‘age’ and ‘salary’ are zero, so they will be included in JSON which you can see in above output.
Usage of NON_EMPTY
The scope of NON_EMPTY is greater than NON_NULL or we can say NON_EMPTY includes NON_NULL in it with others. As per the official document:-
NON_EMPTY + NON_NULL + NON_ABSENT
Properties of a class will not be included during serialization if the value of the property is NULL or Empty. NULL we have already seen. It is for String and reference variables. EMPTY is a little tricky. The definition of emptiness depends on the data type of field.
- A NULL value is also considered as EMPTY.
- For Collections and Map, isEmpty() method is called to check emptiness i.e. without any content.
- For an array and string, the length is checked for emptiness.
A POJO with different data types:-
package JacksonTutorials; import java.util.List; import java.util.Map; public class SeniorEmployee { // private variables or data members of pojo class private String firstName; private String lastName; private String gender; private int age; private double salary; private boolean married; private String[] mobileNo; private Listcars; private Map familyMembers; // Getter and setter methods public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public double getSalary() { return salary; } public void setSalary(double salary) { this.salary = salary; } public boolean getMarried() { return married; } public void setMarried(boolean married) { this.married = married; } public String[] getMobileNo() { return mobileNo; } public void setMobileNo(String[] mobileNo) { this.mobileNo = mobileNo; } public List getCars() { return cars; } public void setCars(List cars) { this.cars = cars; } public Map getFamilyMembers() { return familyMembers; } public void setFamilyMembers(Map familyMembers) { this.familyMembers = familyMembers; } }
Let’s not set any value for any field of POJO class:-
@Test(priority = 1) public void noValuessetForAnyField() throws JsonProcessingException { // Just create an object of Pojo class SeniorEmployee seniorEmployee = new SeniorEmployee(); // Converting a Java class object to a JSON payload as string ObjectMapper objectMapper = new ObjectMapper(); String employeeJson = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(seniorEmployee); System.out.println("Output of noValuessetForAnyField..."); System.out.println(employeeJson); }
Output:-
Output of noValuessetForAnyField... { "firstName" : null, "lastName" : null, "gender" : null, "age" : 0, "salary" : 0.0, "married" : false, "mobileNo" : null, "cars" : null, "familyMembers" : null }
We can see how fields are initialized with default values. Obviously we can ignore NULL values using NON_NULL which we have seen above. Let’s add NON_NULL at the class level and create an object as below:-
@Test(priority = 1) public void noValueSetForArrayListMap() throws JsonProcessingException { // Just create an object of Pojo class SeniorEmployee seniorEmployee = new SeniorEmployee(); seniorEmployee.setFirstName("Amod"); seniorEmployee.setLastName("Mahajan"); seniorEmployee.setAge(29); seniorEmployee.setGender("Male"); seniorEmployee.setSalary(12323.56); seniorEmployee.setMarried(false); // Empty array String[] mobileNo = {}; seniorEmployee.setMobileNo(mobileNo); // Empty list Listcars = new ArrayList (); seniorEmployee.setCars(cars); // Empty Map Map familyMembers = new HashMap<>(); seniorEmployee.setFamilyMembers(familyMembers); // Converting a Java class object to a JSON payload as string ObjectMapper objectMapper = new ObjectMapper(); String employeeJson = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(seniorEmployee); System.out.println("Output of noValueSetForArrayListMap..."); System.out.println(employeeJson); }
Output
Output of valueSetForFields... { "firstName" : "Amod", "lastName" : "Mahajan", "gender" : "Male", "age" : 29, "salary" : 12323.56, "married" : false, "mobileNo" : [ ], "cars" : [ ], "familyMembers" : { } }
You can see NON_NULL did not serve the purpose here as we have empty values not null.
Let’s add NON_EMPTY at class level as:-
import com.fasterxml.jackson.annotation.JsonInclude; @JsonInclude(JsonInclude.Include.NON_EMPTY) public class SeniorEmployee
Let’s rerun both @Test methods again:-
Output of first @Test Method:-
{ "age" : 0, "salary" : 0.0, "married" : false }
Output of second @Test Method:-
{ "firstName" : "Amod", "lastName" : "Mahajan", "gender" : "Male", "age" : 29, "salary" : 12323.56, "married" : false }
I have use annotation at class level but you can use it at property level as well.
Complete Program
package JacksonTutorials; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.testng.annotations.Test; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; public class NonEmptyExample { @Test(priority = 1) public void noValuesSetForAnyField() throws JsonProcessingException { // Just create an object of Pojo class SeniorEmployee seniorEmployee = new SeniorEmployee(); // Converting a Java class object to a JSON payload as string ObjectMapper objectMapper = new ObjectMapper(); String employeeJson = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(seniorEmployee); System.out.println("Output of noValuesSetForAnyField..."); System.out.println(employeeJson); } @Test(priority = 2) public void valueSetForFields() throws JsonProcessingException { // Just create an object of Pojo class SeniorEmployee seniorEmployee = new SeniorEmployee(); seniorEmployee.setFirstName("Amod"); seniorEmployee.setLastName("Mahajan"); seniorEmployee.setAge(29); seniorEmployee.setGender("Male"); seniorEmployee.setSalary(12323.56); seniorEmployee.setMarried(false); String[] mobileNo = new String[2]; mobileNo[0] = "12345"; mobileNo[1] = "67890"; seniorEmployee.setMobileNo(mobileNo); Listcars = new ArrayList (); cars.add("Audi"); cars.add("bmw"); seniorEmployee.setCars(cars); Map familyMembers = new HashMap<>(); familyMembers.put("1", "Father"); familyMembers.put("2", "Mother"); familyMembers.put("3", "Brother"); seniorEmployee.setFamilyMembers(familyMembers); // Converting a Java class object to a JSON payload as string ObjectMapper objectMapper = new ObjectMapper(); String employeeJson = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(seniorEmployee); System.out.println("Output of valueSetForFields..."); System.out.println(employeeJson); } @Test(priority = 3) public void noValueSetForArrayListMap() throws JsonProcessingException { // Just create an object of Pojo class SeniorEmployee seniorEmployee = new SeniorEmployee(); seniorEmployee.setFirstName("Amod"); seniorEmployee.setLastName("Mahajan"); seniorEmployee.setAge(29); seniorEmployee.setGender("Male"); seniorEmployee.setSalary(12323.56); seniorEmployee.setMarried(false); // Empty array String[] mobileNo = {}; seniorEmployee.setMobileNo(mobileNo); // Empty list List cars = new ArrayList (); seniorEmployee.setCars(cars); // Empty Map Map familyMembers = new HashMap<>(); seniorEmployee.setFamilyMembers(familyMembers); // Converting a Java class object to a JSON payload as string ObjectMapper objectMapper = new ObjectMapper(); String employeeJson = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(seniorEmployee); System.out.println("Output of noValueSetForArrayListMap..."); System.out.println(employeeJson); } }
Output (When NON_EMPTY added at class level)
Output of noValuesSetForAnyField... { "age" : 0, "salary" : 0.0, "married" : false } Output of valueSetForFields... { "firstName" : "Amod", "lastName" : "Mahajan", "gender" : "Male", "age" : 29, "salary" : 12323.56, "married" : false, "mobileNo" : [ "12345", "67890" ], "cars" : [ "Audi", "bmw" ], "familyMembers" : { "1" : "Father", "2" : "Mother", "3" : "Brother" } } Output of noValueSetForArrayListMap... { "firstName" : "Amod", "lastName" : "Mahajan", "gender" : "Male", "age" : 29, "salary" : 12323.56, "married" : false }
You can download/clone the above sample project from here.
If you have any doubt, feel free to comment below.
If you like my posts, please like, comment, share and subscribe.
#ThanksForReading
#HappyLearning
Find all Selenium related posts here, all API manual and automation related posts here, and find frequently asked Java Programs here.
Many other topics you can navigate through the menu.