前言
前面介绍了Jackson序列化相关的注解,本篇介绍几个反序列化相关的注解;
目录
- @JsonSetter
- @JsonCreator
- @JsonDeserialize
正文
1. @JsonSetter
该注解用在方法上,目的是代替已有的setter方法,多用在解析Json字符串时,属性匹配不上的情况;
上一篇介绍过的@JsonGetter,就是跟这个注解相对应;
比如我有一个User类,只有一个username属性,但是Json字符串中的属性为name,那么此时就可以通过@JsonSetter来进行匹配;
User类如下所示:
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private String username;
@JsonSetter(value = "name")
public void setName(String name){
this.username = name;
}
}
这里的@JsonSetter的值name
,就是Json字符串中的属性;
此时解析Json字符串,就会把Json字符串中的name
属性解析到user.userName
属性上;
测试代码如下:
String jsonStr = "{\"name\":\"jalon\"}";
ObjectMapper objectMapper = new ObjectMapper();
User user = objectMapper.readValue(jsonStr, User.class);
System.out.println(user);
输出如下:
可以看到,输出正常,name的值解析到了username上;
如果我们不加这个注解,那么解析时就会报错,如下所示:提示name为无法识别的属性
我们平时在解析Json字符串,遇到无法识别的属性时,就可以@JsonSetter来解决;
2. @JsonCreator
这个注解是用来反序列化一个实例的(也就是构造一个类对象);
它跟前面的@JsonValue相对应,@JsonValue是用来序列化一个实例;
应用场景跟上面的类似,都是为了解决属性不匹配的问题;
这里我们还是用上面的那个场景,即:User类,只有一个username属性,但是Json字符串中的属性为name
加了注解后的User类如下所示:
@Data
@NoArgsConstructor
public class User {
private String username;
@JsonCreator
public User(@JsonProperty("name") String username) {
this.username = username;
}
}
可以看到,我们写了一个有参构造函数,将Json字符串中的name属性传进去,给到User.username属性;
测试代码为:
String jsonStr = "{\"name\":\"jalon\"}";
ObjectMapper objectMapper = new ObjectMapper();
User user = objectMapper.readValue(jsonStr, User.class);
System.out.println(user);
输出正常:User(username=jalon)
;
其实这里实现的效果跟第一点的@JsonSetter实现的效果是一样的,都是解决属性不匹配的问题;
3. @JsonDeserialize
这个注解用来配置自定义的反序列化类,它跟前面介绍的@JsonSerialize相对应;
@JsonSerialize用来序列化日期等属性,而@JsonDeserialize则用来反序列化日期等属性;
这里我们再定义一个User类,包含一个日期属性,如下所示:
@Data
@NoArgsConstructor
public class User {
private String username;
@JsonDeserialize(using = CustomDateDeserializer.class)
private Date birth;
}
这里我们将@JsonSerialize注解加在birth属性上,此时反序列化birth时就会触发该注解,然后将日期进行对应的处理;
其中CustomDateDeserializer.class
是我们自定义的日期反序列化类,如下所示:
public class CustomDateDeserializer
extends StdDeserializer<Date> {
private static SimpleDateFormat formatter
= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public CustomDateDeserializer() {
this(null);
}
public CustomDateDeserializer(Class<?> vc) {
super(vc);
}
@Override
public Date deserialize(
JsonParser jsonparser, DeserializationContext context)
throws IOException {
String date = jsonparser.getText();
try {
return formatter.parse(date);
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
}
下面是一个Json字符串,里面包含了一个日期字符串,现在我们对其进行解析:
String jsonStr = "{\"username\":\"jalon\", \"birth\":\"2021-01-01 00:00:00\"}";
ObjectMapper objectMapper = new ObjectMapper();
User user = objectMapper.readValue(jsonStr, User.class);
System.out.println(user);
输出如下:
可以看到,日期被成功解析;
但是输出的日期格式却不是我们配置的格式,这里可能会有点疑惑;
但事实确实如此,因为我们这里日期的格式化只是配置在了setBirth属性上,并没有配置到birth.toString()上面;
所以此时如果需要格式化日期,还需要手动进行一次转换,如下所示:
SimpleDateFormat formatter
= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(formatter.format(user.getBirth()));
到此对于日期的解析就完成了;
如果没有配置反序列化日期的类,那么反序列化时默认会报错,提示“不能将字符串String转为Date类型”;
总结
本篇介绍了三个反序列化会用到的注解,跟上一篇的一一对应:
- @JsonSetter:覆盖已有的setter方法,多用来解决Json字符串和Java对象之间,属性不匹配的问题
- @JsonCreator:反序列化实例,用途同上,多用来解决Json字符串和Java对象之间,属性不匹配的问题
- @JsonDeserialize:多用来反序列化日期,如果不配置,则反序列化日期会报错提示“不能将字符串String转为Date类型”;
评论区