一、问题

在使用JSON反序列化对象时,发现反序列化后对象的部分属性值丢失了,模拟数据如下:

  • 模型类
public class Fruit {

	private String name;
	private String alias;
	private String number;
	private String description;
	private String producer;

	public Fruit(String name, String number) {
		super();
		this.name = name;
		this.number = number;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getAlias() {
		return alias;
	}

	public void setAlias(String alias) {
		this.alias = alias;
	}

	public String getNumber() {
		return number;
	}

	public void setNumber(String number) {
		this.number = number;
	}

	public String getDescription() {
		return description;
	}

	public void setDescription(String description) {
		this.description = description;
	}

	public String getProducer() {
		return producer;
	}

	public void setProducer(String producer) {
		this.producer = producer;
	}

}
  • 测试代码
List<Fruit> fruits = new ArrayList<>();
Fruit apple = new Fruit("苹果", "apple");
Fruit banana = new Fruit("香蕉", "banana");
apple.setDescription("苹果生津、润肺、解署、开胃、醒酒");
banana.setDescription("智慧之果");
fruits.add(apple);
fruits.add(banana);

String json = JSON.toJSONString(fruits);
System.out.println(json);

List<Fruit> result = JSON.parseArray(json, Fruit.class);
for(Fruit fruit : result){
	System.out.println(String.format("%s(%s):%s", fruit.getName(), fruit.getNumber(), fruit.getDescription()));
}
  • 运行结果
[{"description":"苹果生津、润肺、解署、开胃、醒酒","name":"苹果","number":"apple"},{"description":"智慧之果","name":"香蕉","number":"banana"}]
苹果(apple):null
香蕉(banana):null

可以看到从JSON字符串转换后的对象的description属性值丢失了。

二、分析

在Fruit的setXxx方法中打断点,发现并未进入断点,说明没有通过set方法设置数据,而是通过构造函数设置的;Fruit类只有一个可以设置name和number的构造函数,因此反序列化后只有这两个属性有值。

大概调试了下代码,在反序列化时会优先使用默认(无参)构造函数创建对象并通过setXxx方法赋值;没有默认构造函数时,找参数最多的构造函数。

三、解决办法

模型类Fruit需增加无参构造函数(推荐):

...

public Fruit() {
		
}

...

或增加包含description属性的构造函数:

...

public Fruit(String name, String number, String description) {
	super();
	this.name = name;
	this.number = number;
	this.description = description;
}

...
推荐增加无参构造函数,否则构造函数参数要包含所有需要转换的字段。