REST Assured 38 - POJO 的 Getter & Setter 方法如何影响 Serialization 系列化 & Deserialization 反序列化

REST Assured 系列汇总 之 REST Assured 38 - POJO 的 Getter & Setter 方法如何影响 Serialization 系列化 & Deserialization 反序列化

一个典型的 POJO 类由一些 private 字段和相应的 getter & setter 方法或其它访问函数 (不是强制的)组成。本文我们来看看 gettersetter 的存在和不存在对 serialization 序列化和 deserialization 反序列化的影响。

POJO with proper getter and setter methods

下面一个 POJO 类有一些 private 属性和它们 public 的访问函数。为了反映 serializationdeserialization 的过程对 gettersetter 的调用,分别在 gettersetter 方法加入一条 print 语句。

public class EmployeePojoWithGetterSetterMethods {
 
	// 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() {
		System.out.println("Getter - First Name : "+ firstName);
		return firstName;
	}
	public void setFirstName(String firstName) {
		System.out.println("Setter - First Name : "+ firstName);
		this.firstName = firstName;
	}
	public String getLastName() {
		System.out.println("Getter - Last Name : "+ lastName);
		return lastName;
	}
	public void setLastName(String lastName) {
		System.out.println("Setter - Last Name : "+ lastName);
		this.lastName = lastName;
	}
	public String getGender() {
		System.out.println("Getter - Gender : "+ gender);
		return gender;
	}
	public void setGender(String gender) {
		System.out.println("Setter - Gender : "+ gender);
		this.gender = gender;
	}
	public int getAge() {
		System.out.println("Getter - Age : "+ age);
		return age;
	}
	public void setAge(int age) {
		System.out.println("Setter - Age : "+ age);
		this.age = age;
	}
	public double getSalary() {
		System.out.println("Getter - Salary : "+ salary);
		return salary;
	}
	public void setSalary(double salary) {
		System.out.println("Setter - Salary : "+ salary);
		this.salary = salary;
	}
	public boolean getMarried() {
		System.out.println("Getter - Married : "+ married);
		return married;
	}
	public void setMarried(boolean married) {
		System.out.println("Setter - Married : "+ married);
		this.married = married;
	} 	
}

serialization 序列化 上面的 POJO 类:

@Test
	public void serializeWithBothGetterSetter() throws JsonProcessingException {
		// Just create an object of Pojo class
		EmployeePojoWithGetterSetterMethods employeePojoWithGetterSetterMethods = new EmployeePojoWithGetterSetterMethods();
		employeePojoWithGetterSetterMethods.setFirstName("Amod");
		employeePojoWithGetterSetterMethods.setLastName("Mahajan");
		employeePojoWithGetterSetterMethods.setAge(29);
		employeePojoWithGetterSetterMethods.setGender("Male");
		employeePojoWithGetterSetterMethods.setSalary(12323.56);
		employeePojoWithGetterSetterMethods.setMarried(false);
		
		// Converting a Java class object to a JSON payload as string
		System.out.println("Serialization...");
		ObjectMapper objectMapper = new ObjectMapper();
		String employeeJson = objectMapper.writerWithDefaultPrettyPrinter()
				.writeValueAsString(employeePojoWithGetterSetterMethods);
		System.out.println(employeeJson);
	}

输出:

Setter - First Name : Amod
Setter - Last Name : Mahajan
Setter - Age : 29
Setter - Gender : Male
Setter - Salary : 12323.56
Setter - Married : false
Serialization...
Getter - First Name : Amod
Getter - Last Name : Mahajan
Getter - Gender : Male
Getter - Age : 29
Getter - Salary : 12323.56
Getter - Married : false
{
  "firstName" : "Amod",
  "lastName" : "Mahajan",
  "gender" : "Male",
  "age" : 29,
  "salary" : 12323.56,
  "married" : false
}

因为实例化对象后设置了一些值, 所以 setter 方法被执行。序列化时,从输出可以看出,getter 方法被内部执行。 很明显,为了组成一个JSON需要获取字段的值,这些值可以通过 getter 方法来获取。

deserialize with the above POJO class

@Test
	public void deserializeWithBothGetterSetter() throws JsonProcessingException {
		String jsonString = "{\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" + 
				"}";
		
		System.out.println("Deserialization...");
		ObjectMapper objectMapper = new ObjectMapper();
		EmployeePojoWithGetterSetterMethods employeePojoWithGetterSetterMethods = objectMapper.readValue(jsonString, EmployeePojoWithGetterSetterMethods.class);
		
		System.out.println("First name :- "+employeePojoWithGetterSetterMethods.getFirstName());
		System.out.println("Last name :- "+employeePojoWithGetterSetterMethods.getLastName());
		System.out.println("Age :- "+employeePojoWithGetterSetterMethods.getAge());
		System.out.println("Gender :- "+employeePojoWithGetterSetterMethods.getGender());
		System.out.println("Salary :- "+employeePojoWithGetterSetterMethods.getSalary());
		System.out.println("Married :- "+employeePojoWithGetterSetterMethods.getMarried());
		
	}

输出:

Deserialization...
Setter - First Name : Amod
Setter - Last Name : Mahajan
Setter - Gender : Male
Setter - Age : 29
Setter - Salary : 12323.56
Setter - Married : false
Getter - First Name : Amod
First name :- Amod
Getter - Last Name : Mahajan
Last name :- Mahajan
Getter - Age : 29
Age :- 29
Getter - Gender : Male
Gender :- Male
Getter - Salary : 12323.56
Salary :- 12323.56
Getter - Married : false
Married :- false

反序列化时,从输出可以看出 setter 方法被内部调用。为了输出值, getter 方法被调用。

结论,Serialization 调用到 Getter 方法,Deserialization 调用 Setter 方法。

如果 setter 和 getter 方法缺失,将会发生什么?

POJO with only getter methods

删除所有的 setter 方法,那么 在POJO 类中只有 getter 方法。

public class EmployeeWithGetterMethodsOnly {
 
	// 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 methods only
	public String getFirstName() {
		System.out.println("Getter - First Name : "+ firstName);
		return firstName;
	}
	
	public String getLastName() {
		System.out.println("Getter - Last Name : "+ lastName);
		return lastName;
	}
	
	public String getGender() {
		System.out.println("Getter - Gender : "+ gender);
		return gender;
	}
	
	public int getAge() {
		System.out.println("Getter - Age : "+ age);
		return age;
	}
	
	public double getSalary() {
		System.out.println("Getter - Salary : "+ salary);
		return salary;
	}
	
	public boolean getMarried() {
		System.out.println("Getter - Married : "+ married);
		return married;
	}
		
}

序列化上面的 POJO 类

@Test
	public void serializeWithGetterOnly() throws JsonProcessingException {
		// Just create an object of Pojo class but we can set values as we do not have any setter methods
		EmployeeWithGetterMethodsOnly employeeWithGetterMethodsOnly = new EmployeeWithGetterMethodsOnly();
			
		// Converting a Java class object to a JSON payload as string
		ObjectMapper objectMapper = new ObjectMapper();
		String employeeJson = objectMapper.writerWithDefaultPrettyPrinter()
				.writeValueAsString(employeeWithGetterMethodsOnly);
		System.out.println("Serialization...");
		System.out.println(employeeJson);
	}

输出:

Getter - First Name : null
Getter - Last Name : null
Getter - Gender : null
Getter - Age : 0
Getter - Salary : 0.0
Getter - Married : false
Serialization...
{
  "firstName" : null,
  "lastName" : null,
  "gender" : null,
  "age" : 0,
  "salary" : 0.0,
  "married" : false
}

因为没有 setter 方法,所以没法 serialize 一些设定的值。所有类的字段成员按默认值进行初始化,从输出看出,序列化过程中调用了 getter 方法,只是获取了默认的值。

deserialize with the above POJO class

@Test
	public void deserializeWithGetterOnly() throws JsonProcessingException {
		String jsonString = "{\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" + 
				"}";
		
		System.out.println("Deserialization...");
		ObjectMapper objectMapper = new ObjectMapper();
		EmployeeWithGetterMethodsOnly employeeWithGetterMethodsOnly = objectMapper.readValue(jsonString, EmployeeWithGetterMethodsOnly.class);
		
		System.out.println("First name :- "+employeeWithGetterMethodsOnly.getFirstName());
		System.out.println("Last name :- "+employeeWithGetterMethodsOnly.getLastName());
		System.out.println("Age :- "+employeeWithGetterMethodsOnly.getAge());
		System.out.println("Gender :- "+employeeWithGetterMethodsOnly.getGender());
		System.out.println("Salary :- "+employeeWithGetterMethodsOnly.getSalary());
		System.out.println("Married :- "+employeeWithGetterMethodsOnly.getMarried());
		
		
	}

输出:

Deserialization...
Getter - First Name : Amod
First name :- Amod
Getter - Last Name : Mahajan
Last name :- Mahajan
Getter - Age : 29
Age :- 29
Getter - Gender : Male
Gender :- Male
Getter - Salary : 12323.56
Salary :- 12323.56
Getter - Married : false
Married :- false

没有 setter 方法, deserialization 也是没有问题的。如果 deserialization 一个 有 getter 和 setter 方法的 POJO 类时,setter 方法会被内部执行,跟我们上面的例子是不一样的。

如果 POJO 类只有 getter 方法, 你无法 serialize 序列化想要设定的值,但是可以很方便的反序列化 deserialize 它。所以没有必要为 deserialize 专用的 setter 方法。

如果 getter 方法缺失,POJO 只有 setter 方法,将会发生什么?

POJO with only setter methods

public class EmployeePojoWithSetterMethodsOnly {
 
	// 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;
	
	// Setter methods
	
	public void setFirstName(String firstName) {
		System.out.println("Setter - First Name : "+ firstName);
		this.firstName = firstName;
	}
	
	public void setLastName(String lastName) {
		System.out.println("Setter - Last Name : "+ lastName);
		this.lastName = lastName;
	}
	
	public void setGender(String gender) {
		System.out.println("Setter - Gender : "+ gender);
		this.gender = gender;
	}
	
	public void setAge(int age) {
		System.out.println("Setter - Age : "+ age);
		this.age = age;
	}
	
	public void setSalary(double salary) {
		System.out.println("Setter - Salary : "+ salary);
		this.salary = salary;
	}
	
	public void setMarried(boolean married) {
		System.out.println("Setter - Married : "+ married);
		this.married = married;
	} 	
}

serialize with the above POJO class

@Test
	public void serializeWithSetterOnly() throws JsonProcessingException {
		// Just create an object of Pojo class
		EmployeePojoWithSetterMethodsOnly employeePojoWithSetterMethodsOnly = new EmployeePojoWithSetterMethodsOnly();
		employeePojoWithSetterMethodsOnly.setFirstName("Amod");
		employeePojoWithSetterMethodsOnly.setLastName("Mahajan");
		employeePojoWithSetterMethodsOnly.setAge(29);
		employeePojoWithSetterMethodsOnly.setGender("Male");
		employeePojoWithSetterMethodsOnly.setSalary(12323.56);
		employeePojoWithSetterMethodsOnly.setMarried(false);
		
		// Converting a Java class object to a JSON payload as string
		System.out.println("Serialization...");
		ObjectMapper objectMapper = new ObjectMapper();
		String employeeJson = objectMapper.writerWithDefaultPrettyPrinter()
				.writeValueAsString(employeePojoWithSetterMethodsOnly);
		System.out.println(employeeJson);
	}

输出:

Setter - Last Name : Mahajan
Setter - Age : 29
Setter - Gender : Male
Setter - Salary : 12323.56
Setter - Married : false
Serialization...
FAILED: serializeWithSetterOnly
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class GameOfGetterSetterPOJO.EmployeePojoWithSetterMethodsOnly and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS)
	at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:77)
	at com.fasterxml.jackson.databind.SerializerProvider.reportBadDefinition(SerializerProvider.java:1277)
	at com.fasterxml.jackson.databind.DatabindContext.reportBadDefinition(DatabindContext.java:400)

发生异常 “No serializer found”,很明显,序列化时找不到 有效的 getter 方法。

deserialize with the above POJO class

@Test
	public void deserializeWithSetterOnly() throws JsonProcessingException {
		String jsonString = "{\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" + 
				"}";
		
		System.out.println("Deserialization...");
		ObjectMapper objectMapper = new ObjectMapper();
		EmployeePojoWithSetterMethodsOnly employeePojoWithSetterMethodsOnly = objectMapper.readValue(jsonString, EmployeePojoWithSetterMethodsOnly.class);
	}

输出deserialization时内部调用了 setter 方法

Deserialization...
Setter - First Name : Amod
Setter - Last Name : Mahajan
Setter - Gender : Male
Setter - Age : 29
Setter - Salary : 12323.56

因为没有 getter 方法,我们不能获取属性的值。但是这不并不意味着属性不能初始化。我们加一些其它的 getter 方法来获取值。

public class EmployeePojoWithSetterMethodsOnly {
 
	// 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;
	
	// Setter methods
	
	public void setFirstName(String firstName) {
		System.out.println("Setter - First Name : "+ firstName);
		this.firstName = firstName;
	}
	
	public void setLastName(String lastName) {
		System.out.println("Setter - Last Name : "+ lastName);
		this.lastName = lastName;
	}
	
	public void setGender(String gender) {
		System.out.println("Setter - Gender : "+ gender);
		this.gender = gender;
	}
	
	public void setAge(int age) {
		System.out.println("Setter - Age : "+ age);
		this.age = age;
	}
	
	public void setSalary(double salary) {
		System.out.println("Setter - Salary : "+ salary);
		this.salary = salary;
	}
	
	public void setMarried(boolean married) {
		System.out.println("Setter - Married : "+ married);
		this.married = married;
	}
 
	public String alternateGetFirstName() {
		return firstName;
	}
 
	public String alternateGetLastName() {
		return lastName;
	}
 
	public String alternateGetGender() {
		return gender;
	}
 
	public int alternateGetAge() {
		return age;
	}
 
	public double alternateGetSalary() {
		return salary;
	}
 
	public boolean alternateGetMarried() {
		return married;
	} 	
}

Updated deserialize code

@Test
	public void deserializeWithSetterOnly() throws JsonProcessingException {
		String jsonString = "{\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" + 
				"}";
		
		System.out.println("Deserialization...");
		ObjectMapper objectMapper = new ObjectMapper();
		EmployeePojoWithSetterMethodsOnly employeePojoWithSetterMethodsOnly = objectMapper.readValue(jsonString, EmployeePojoWithSetterMethodsOnly.class);
		
		System.out.println("First name :- "+employeePojoWithSetterMethodsOnly.alternateGetFirstName());
		System.out.println("Last name :- "+employeePojoWithSetterMethodsOnly.alternateGetLastName());
		System.out.println("Age :- "+employeePojoWithSetterMethodsOnly.alternateGetAge());
		System.out.println("Gender :- "+employeePojoWithSetterMethodsOnly.alternateGetGender());
		System.out.println("Salary :- "+employeePojoWithSetterMethodsOnly.alternateGetSalary());
		System.out.println("Married :- "+employeePojoWithSetterMethodsOnly.alternateGetMarried());
		
		
	}

输出:

Deserialization...
Setter - First Name : Amod
Setter - Last Name : Mahajan
Setter - Gender : Male
Setter - Age : 29
Setter - Salary : 12323.56
Setter - Married : false
First name :- Amod
Last name :- Mahajan
Age :- 29
Gender :- Male
Salary :- 12323.56
Married :- false

所以如果你只有 setter 方法,即使有其它的 getter 方法,你也无法 serialize POJO 类。但是可以 deserialize,还可以通过其它的 getter 方法来获取字段的值。

结论:

serialization 时内部会调用 getter 方法,如果没有 getter 方法,即使有其它形式的获取属性值的方法,也无法进行 serialization。deserialization 时会内部调用 setter 方法,但是没有 setter 方法也不影响 deserialization。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值