REST Assured 37 - @JsonInclude Annotation – ignore fields with Null & Empty Values in Payload

Keywords: JSON API testing

REST Assured series summary REST Assured 37 - @JsonInclude Annotation – ignore fields with null & empty values in Payload

Jackson libray is an important annotation @JsonInclude, which can clear the properties with default value, null and empty. This article will learn about ignoring null and empty attributes in paylaod.

Maven Dependency
To use an annotation provided by the Jackson API, we need to import the Jackson library. I am using the maven build tool.

Try to use Central Maven Repository The latest Jackson dependency package, for example:

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.12.5</version>
</dependency>

Of course, some dependency packages will also pass dependency on Jackson, so there is no need to add Jackson dependency, such as json schema validator

 <!-- json schema validation -->
  <dependency>
      <groupId>io.rest-assured</groupId>
      <artifactId>json-schema-validator</artifactId>
      <version>4.3.0</version>
 </dependency>

Previous article @JsonInclude Annotation ignores the default value Yes, I understand that there are different values in the Include enumeration.

Usage of NON_NULL

In the Java language, the values of default variables are as follows:

Data TypeDefault Value (for fields)
byte0
short0
int0
long0L
float0.0f
double0.0d
char'u0000'
String (or any object)null
booleanfalse

The most dangerous default value is null. If we do not verify the variable with null value, an exception NullPointerException may occur to terminate the program. Sometimes it's not good to ignore all default values. We just want to ignore null values. So in this case, we can use the non of Include_ Null enumeration value, as follows:

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;
	} 	
}

Convert Java Object to JSON Object

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 do not set values for the fields' lastName ',' gender ',' age 'and' salary ', because the default values of the fields' lastName' and 'gender' are NULL, so they are ignored in the serialization process. The default values of the fields' age 'and' salary 'are 0, so they are included in JSON, which can be seen from the output.

Usage of NON_EMPTY
NON_EMPTY range is greater than NON_NULL, or NON_EMPTY includes NON_NULL and others, according to Official documents:

NON_EMPTY + NON_NULL + NON_ABSENT

If the property value of the class is NULL or EMPTY, it may need to be ignored during serialization. NULL, which we learned earlier, is mainly used for String and reference type variables. EMPTY is a bit tricky. The definition of NULL depends on the data type.

  1. A NULL value can be considered EMPTY
  2. For Collection and Map, you can call isEmpty() method to determine whether it is EMPTY
  3. For a phase array or string, you can judge whether it is EMPTY by its length
    A NULL value is also considered as EMPTY.

A POJO class with different types of data

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 List<String> cars;
	private Map<String,String> 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<String> getCars() {
		return cars;
	}
	public void setCars(List<String> cars) {
		this.cars = cars;
	}
	public Map<String, String> getFamilyMembers() {
		return familyMembers;
	}
	public void setFamilyMembers(Map<String, String> familyMembers) {
		this.familyMembers = familyMembers;
	}
}

No value is set

@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);
	}
{
  "firstName" : null,
  "lastName" : null,
  "gender" : null,
  "age" : 0,
  "salary" : 0.0,
  "married" : false,
  "mobileNo" : null,
  "cars" : null,
  "familyMembers" : null
}

We see that all fields are default values. We can use NON_NULL to ignore all NULL values above. Let's add non to the Class level_ NULL, create the following object:

@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
		List<String> cars = new ArrayList<String>();
		seniorEmployee.setCars(cars);
		
		// Empty Map
		Map<String,String> 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" : { }
}

It can be seen that NON_NULL does not achieve the purpose of ignoring the empty value. We put NON_EMPTY is added to the class level.

import com.fasterxml.jackson.annotation.JsonInclude;
 
@JsonInclude(JsonInclude.Include.NON_EMPTY)
public class SeniorEmployee

Return to the first @ Test method and execute it. The output results are as follows:

{
  "age" : 0,
  "salary" : 0.0,
  "married" : false
}

Return to the second @ Test method and execute it. The output results are as follows:

{
  "firstName" : "Amod",
  "lastName" : "Mahajan",
  "gender" : "Male",
  "age" : 29,
  "salary" : 12323.56,
  "married" : false
}

You can see that all NULL and EMPTY values are ignored. Of course, you can also add annotation to the attribute level.

Full code:

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
 
import org.junit.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);
		
		List<String> cars = new ArrayList<String>();
		cars.add("Audi");
		cars.add("bmw");
		seniorEmployee.setCars(cars);
		
		Map<String,String> 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<String> cars = new ArrayList<String>();
		seniorEmployee.setCars(cars);
		
		// Empty Map
		Map<String,String> 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 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
}

Posted by Infinitus 8 on Sun, 12 Sep 2021 18:52:01 -0700