REST Assured 系列汇总 之 REST Assured 42 - 利用Jackson API ObjectMapper – Deserialization 忽略 Unknown Properties
前提条件:
关于 @JsonIgnoreProperties:
在 deserialization 中,利用 Jackson 提供的 @JsonIgnoreProperties annotation 可以忽略一些 unknown 属性,以防抛异常,详情请参考:
@JsonIgnoreProperties Annotation - Deserialization 忽略 Unknown Properties
Required Java Library
因为我们用到 Jackson API, 所以确保导入 Jackson Databind 依赖包。
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.11.1</version>
</dependency>
什么是 known 和 unknown 属性?
在进入主题之前,先来了解一下有关 known 和 unkonw 属性。如果一个属性存在于一个 POJO 类里,那么这个属性就是这个 POJO 类的 known 属性,反之这个属性不存在这个 POJO 类中就是 unkown 属性。让我们先看一个实例,known 属性在 deserialization 过程中缺失,将会发生什么?
在deserialization过程中缺失 known 属性
POJO 类:
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;
}
}
Deserialize 缺失一些 known 属性
在 JSON 字符串不会包含所有 known 属性,如下:
import org.junit.Test;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class DeserializationWithMissingKnownProperties {
@Test
public void deserializationWithMissingKnownProperties() throws JsonMappingException, JsonProcessingException
{
String employeeString = "{\r\n" +
" \"firstName\" : \"Amod\",\r\n" +
" \"lastName\" : \"Mahajan\",\r\n" +
" \"gender\" : \"Male\"\r\n" +
"}";
ObjectMapper objectMapper = new ObjectMapper();
//objectMapper.con
Employee employee = objectMapper.readValue(employeeString, Employee.class);
System.out.println("Deserialization...");
System.out.println("First name :- "+employee.getFirstName());
System.out.println("Last name :- "+employee.getLastName());
System.out.println("Age :- "+employee.getAge());
System.out.println("Gender :- "+employee.getGender());
System.out.println("Salary :- "+employee.getSalary());
System.out.println("Married :- "+employee.getMarried());
}
}
输出:
Deserialization...
First name :- Amod
Last name :- Mahajan
Age :- 0
Gender :- Male
Salary :- 0.0
Married :- false
在 JSON 字符串,有三个 known 属性 age, salary, 和 married 是缺失的,deserialization 反序列化后这些缺失的属性都是默认值。不会因为缺失部分 known 属性导致异常。
deserialization 反序列化一些额外的 unknown 属性
前面实例中,我们在 JSON 中缺失了部分 known 属性。现在我们来 JSON 中增加一些额外的 unknown 属性,观察一下将有啥行为。
Deserialize 反序列化一些 unknown 属性
import org.testng.annotations.Test;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class DeserializationWithAdditionalUnknownProperties {
@Test
public void deserializationWithAdditionalUnknownProperties() throws JsonMappingException, JsonProcessingException
{
String employeeString = "{\r\n" +
" \"firstName\" : \"Amod\",\r\n" +
" \"lastName\" : \"Mahajan\",\r\n" +
" \"gender\" : \"Male\",\r\n" +
" \"age\" : 29,\r\n" +
" \"salary\" : 12323.56,\r\n" +
" \"married\" : false,\r\n" +
" \"fullName\" : \"Amod Mahajan Gupta\",\r\n" +
" \"eligibleForVote\" : false\r\n" +
"}";
ObjectMapper objectMapper = new ObjectMapper();
//objectMapper.con
Employee employee = objectMapper.readValue(employeeString, Employee.class);
System.out.println("Deserialization...");
System.out.println("First name :- "+employee.getFirstName());
System.out.println("Last name :- "+employee.getLastName());
System.out.println("Age :- "+employee.getAge());
System.out.println("Gender :- "+employee.getGender());
System.out.println("Salary :- "+employee.getSalary());
System.out.println("Married :- "+employee.getMarried());
}
}
在 JSON 字符串中包含了一些 unknown 属性,如 fullName 和 eligibleForVote。
输出:
FAILED: deserializationWithMissingKnownProperties
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "fullName" (class JacksonTutorials.Employee), not marked as ignorable (6 known properties: "lastName", "married", "salary", "firstName", "age", "gender"])
at [Source: (String)"{
"firstName" : "Amod",
"lastName" : "Mahajan",
"gender" : "Male",
"age" : 29,
"salary" : 12323.56,
"married" : false,
"fullName" : "Amod Mahajan Gupta",
"eligibleForVote" : false
}"; line: 8, column: 17] (through reference chain: JacksonTutorials.Employee["fullName"])
当遇到第一个 unknown 属性 “fullName”时,deserialization 反序列化失败,输出中还列出了所有 known 的属性。
ObjectMapper configuration to ignore unknown properties
在上篇文章中,deserialization 过程中利用 @JsonIgnoreProperties 作用在 class 级别上忽略一些 unknown 属性。但是如果你不能访问到 POJO 类 或不允许更改 POJO 类,我们还可以通过 ObjectMapper 配置达成相同的效果。
需要用到 DeserializationFeature 枚举,将 “FAIL_ON_UNKNOWN_PROPERTIES” 设置为 false,就没有必要更改 POJO 类。
ObjectMapper Configuration Code
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.Test;
import java.io.IOException;
public class DeserializationWithAdditionalUnknownPropertiesObjectMapper {
@Test
public void deserializationWithAdditionalUnknownProperties() throws IOException {
String employeeString = "{\r\n" +
" \"firstName\" : \"Amod\",\r\n" +
" \"lastName\" : \"Mahajan\",\r\n" +
" \"gender\" : \"Male\",\r\n" +
" \"age\" : 29,\r\n" +
" \"salary\" : 12323.56,\r\n" +
" \"married\" : false,\r\n" +
" \"fullName\" : \"Amod Mahajan Gupta\",\r\n" +
" \"eligibleForVote\" : false\r\n" +
"}";
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
//objectMapper.con
Employee employee = objectMapper.readValue(employeeString, Employee.class);
System.out.println("Deserialization...");
System.out.println("First name :- "+employee.getFirstName());
System.out.println("Last name :- "+employee.getLastName());
System.out.println("Age :- "+employee.getAge());
System.out.println("Gender :- "+employee.getGender());
System.out.println("Salary :- "+employee.getSalary());
System.out.println("Married :- "+employee.getMarried());
}
}
输出:
Deserialization...
First name :- Amod
Last name :- Mahajan
Age :- 29
Gender :- Male
Salary :- 12323.56
Married :- false
可以看出, JSON 字符串中包含一些 unkown 属性,serialization 成功,没有异常抛出。