侧边栏壁纸
  • 累计撰写 90 篇文章
  • 累计创建 95 个标签
  • 累计收到 10 条评论

目 录CONTENT

文章目录

Jackson反序列化的有关注解

汤圆学Java
2022-02-25 / 0 评论 / 0 点赞 / 171 阅读 / 4,207 字
温馨提示:
本文最后更新于 2022-02-25,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

前言

前面介绍了Jackson序列化相关的注解,本篇介绍几个反序列化相关的注解;

目录

  1. @JsonSetter
  2. @JsonCreator
  3. @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);

输出如下:

image-20220221183419368

可以看到,输出正常,name的值解析到了username上;

如果我们不加这个注解,那么解析时就会报错,如下所示:提示name为无法识别的属性

image-20220221183521953

我们平时在解析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);

输出如下:

image-20220221185928863

可以看到,日期被成功解析;

但是输出的日期格式却不是我们配置的格式,这里可能会有点疑惑;

但事实确实如此,因为我们这里日期的格式化只是配置在了setBirth属性上,并没有配置到birth.toString()上面;

所以此时如果需要格式化日期,还需要手动进行一次转换,如下所示:

SimpleDateFormat formatter
    = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(formatter.format(user.getBirth()));

到此对于日期的解析就完成了;

如果没有配置反序列化日期的类,那么反序列化时默认会报错,提示“不能将字符串String转为Date类型”;

image-20220221190838136

总结

本篇介绍了三个反序列化会用到的注解,跟上一篇的一一对应:

  1. @JsonSetter:覆盖已有的setter方法,多用来解决Json字符串和Java对象之间,属性不匹配的问题
  2. @JsonCreator:反序列化实例,用途同上,多用来解决Json字符串和Java对象之间,属性不匹配的问题
  3. @JsonDeserialize:多用来反序列化日期,如果不配置,则反序列化日期会报错提示“不能将字符串String转为Date类型”;
0

评论区