反序列化通常较为简单,是因为反序列使用的JSON字符串基本都是序列化生成的,其次反序列化需要考虑的问题较少,且大部分问题与序列化是重复的。

  本篇介绍一些零散的,常见的反序列过程中出现的问题。

1、空转null

假设存在需求,json串的value为空字符串,想把属性值转换为null。

启用DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT即可。

2、@JsonCreator

默认情况下,反序列化会调用属性的set和get方法,若想调用对象的构造器。

第一种方式,在构造器上添加@JsonCreator注解,在参数上添加@JsonProperty注解,示例如下:

@JsonCreator
public Employee( @JsonProperty("name") String name, 
@JsonProperty("dept") String dept){
    this.name = name;
    this.dept = dept;
}

  第二种方式,在构造器上添加@ConstructorProperties注解,它的value值为字符串数组,顺序与参数的顺序保持一致。即数组中的第一个键值对应构造器的第一个参数,依次类推。

@ConstructorProperties({"name","dept"})
public Employee(String name, String dept) {
    this.name = name;
    this.dept = dept;
}

3、设定属性类型

假设存在需求,对象的属性类型为父类,反序列化时需要指定为特定的子类型。

可以在属性上添加@JsonDeserialize注解,as属性的值为子类的值。例如

// 假设Shape类的子类有Circle, Rectangle, Square等。
@JsonDeserialize(as = Circle.class);
private Shape shape;

4、@JsonInject

假设存在某对象Obj,它存在currentTime属性,实时记录当前的时间。这种情况下,不能使用序列化时的值,只能动态更新。具体实现方式如下:

第一步,在属性上添加@JsonInject注解。

@JsonInject("currentTime")
private Date currentTime;

  第二步,在反序列化时动态注入该键值,

// 创建InjectableValues对象
InjectableValues values = new InjectableValues.Std();

// currentTime与time属性上@JsonInject注解的值对应
((InjectableValues.Std)values).addValue("currentTime", LocalDateTime.now());

// 注入
ObjectMapper om = new ObjectMapper();
om.setInjectableValues(values);

5、@JsonMerge

更新对象的含义是指,通过JSON字符串对已存在的对象实例进行更新。

第一步,调用objectMapper.readForUpadte方法创建ObjectReader对象,

ObjectReader reader = objectReader.readForUpdating(existingObject);

  第二步,调用reader的readValue方法,参数为JSON字符串。

Object updatedObject = objectReader.readValue(inputJson);

  这种方式下若自定义对象属性引用不是null,是不会更新自定义对象属性的。解决它的方案是在自定义对象属性上添加@JsonMerge

@JsonMerge
private Address address;

  概念类似于深克隆与浅克隆,添加@JsonMerge,深克隆,未添加,浅克隆。