REST Assured 系列汇总 之 REST Assured 37 - @JsonInclude Annotation – Payload 中忽略值为Null & Empty Values的字段
Jackson libray 一个重要的 annotation @JsonInclude,它可以清除值为默认值,null, empty的属性。本文将了解 paylaod中忽略值为 null 和 empty的属性。
Maven Dependency
因为要使用 Jackson API提供的一个 annotation,我们需要导入 Jackson library,我在用的是 maven 构建工具。
尽量用 Central Maven Repository 最新的 Jackson 依赖包,例如如下:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.5</version>
</dependency>
当然有些依赖包也会传递依赖Jackson,就不用再添加 Jackson依赖了,如 json schema validator
<!-- json schema validation -->
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>json-schema-validator</artifactId>
<version>4.3.0</version>
</dependency>
前面文章@JsonInclude Annotation 忽略默认值有了解 Include 枚举中有不同的值。
Usage of NON_NULL
Java语言中,默认变量的值如下:
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 |
最危险的默认值就是 NULL ,如果我们没有验证值为 null 的变量,可能会出现异常 NullPointerException 终止程序。有时忽略所有默认值并非是好的,我们只是想忽略 NULL 值。所以这种情况,我们可以用 Include 的 NON_NULL 枚举值,如下:
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;
}
}
将 Java Object 转换成 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);
}
}
输出:
{
"firstName" : "Amod",
"age" : 0,
"salary" : 0.0,
"married" : true
}
我们没有对字段 ‘lastName’, ‘gender’,’age’ 和 ‘salary’ 设置值,因为字段 ‘lastName’ 和 ‘gender’ 默认值都是 NULL,所以在序列化过程中是被忽略了。而字段 ‘age’ 和 ‘salary’ 默认值均为 0 , 所以被包含在JSON中,可以从输出中看出。
Usage of NON_EMPTY
NON_EMPTY 范围大于 NON_NULL,或则可以说 NON_EMPTY 包括 NON_NULL 和其它,根据官方文档:
NON_EMPTY + NON_NULL + NON_ABSENT
如果类的属性值是 NULL 或 Empty,在序列化时可能需要忽略。NULL 我们前面了解过,主要用于 String 和 引用类型变量。EMPTY有点棘手, 空值的定义取决于数据类型。
- 一个 NULL 值可以认为是 EMPTY
- 对于 Collection 和 Map, 可以调用 isEmpty() 方法判断是否为EMPTY
- 对一个相数组或字符串,通过长度可以判断是否为EMPTY
A NULL value is also considered as EMPTY.
一个有不同类型数据的POJO类
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;
}
}
不设置任何值
@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
}
我们看到字段都是默认值。我们可以通过 NON_NULL 来忽略上面所有 NULL值,让我们在Class级别上加上 NON_NULL ,创建如下对象:
@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 of valueSetForFields...
{
"firstName" : "Amod",
"lastName" : "Mahajan",
"gender" : "Male",
"age" : 29,
"salary" : 12323.56,
"married" : false,
"mobileNo" : [ ],
"cars" : [ ],
"familyMembers" : { }
}
可以看出 NON_NULL 没有实现忽略 empty 值的目的。我们把 NON_EMPTY 加到 class 级别。
import com.fasterxml.jackson.annotation.JsonInclude;
@JsonInclude(JsonInclude.Include.NON_EMPTY)
public class SeniorEmployee
再回到 第一个@Test 方法并执行,输出结果如下:
{
"age" : 0,
"salary" : 0.0,
"married" : false
}
再回到 第二个@Test 方法并执行,输出结果如下:
{
"firstName" : "Amod",
"lastName" : "Mahajan",
"gender" : "Male",
"age" : 29,
"salary" : 12323.56,
"married" : false
}
可以看出所有 NULL 和 EMPTY的值都忽略了,当然也可以将 annotation 加到属性级别。
完整代码:
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 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
}