反序列化通常较为简单,是因为反序列使用的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,深克隆,未添加,浅克隆。