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

目 录CONTENT

文章目录

Jackson序列化的有关注解-部分

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

前言

Jackson中注释有很多,这里我们先介绍部分跟序列化有关的,其他的后面再陆续介绍;

目录

  1. @JsonGetter
  2. @JsonValue
  3. @JsonSerialize

正文

1. @JsonGetter

该注解用在方法上,目的是替换已有的getter方法;

比如我有一个User类,如下所示:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {

    private String username;
    private String nickname;

}

这里默认的getter都是通过@Data注解自动添加的;

此时如果我们想要用其他的方法覆盖默认的getUsername方法,就可以用@JsonGetter来实现,代码如下:

@JsonGetter(value = "username")
public String getMyName(){
    return "actual name";
}

这里注解的值value='username',表示username的getter方法会被这里的方法覆盖(默认的getter会失效);

用下面的代码可以进行测试:

ObjectMapper objectMapper = new ObjectMapper();
User user = new User("jalon", "test");
String s = objectMapper.writeValueAsString(user);
System.out.println(s);

运行后,输出如下:

image-20220221154125155

可以看到,输出的并不是构造时的数据,而是@JsonGetter注解的方法所返回的数据;

这个注解@JsonGetter改变的只是序列化的值,如果我们直接通过user.getUsername()来获取,返回的还会是构造时的数据jalon

2. @JsonValue

@JsonValue的目的是为了序列化整个实例;

如果用了@JsonValue注解,那么序列化时只会从@JsonValue注解的方法上执行,不再去执行其他的序列化;

比如,我们将@JsonValue注解在getUsername()方法上,如下所示;此时Jackson只会序列化username属性,其他的属性比如nickname不会被序列化;

@JsonValue
public String getUsername(){
    return username;
}

测试代码如下:

ObjectMapper objectMapper = new ObjectMapper();
User user = new User("jalon", "test");
String s = objectMapper.writeValueAsString(user);
System.out.println(s);

输出如下:

image-20220221155703365

可以看到,输出只有一个username属性,这是因为Jackson此时只去@JsonValue下面进行了序列化,其他的getter方法没进行序列化

注:此时反序列化是无法成功的,因为我们已经修改了序列化的结构;反序列化可参考@JsonCreator

不过常用的做法是将@JsonValue用在toString方法上,用来覆盖默认的转换行为,如下所示:

@JsonValue
@Override
public String toString() {
    return "User-@JsonValue{" +
        "username='" + username + '\'' +
        ", nickname='" + nickname + '\'' +
        '}';
}

此时运行输出,就会看到完整的数据了,如下所示:

image-20220221160259319

3. @JsonSerialize

这个注解之前接触过,主要用来序列化日期;

我们重新定义一个User类,包含一个生日,如下所示:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {

    private String username;

    private Date birth;

    @JsonSerialize(using = CustomDateSerializer.class)
    public Date getBirth(){
        return birth;
    }
}

这里我们将@JsonSerialize注解加在getBirth方法上,此时序列化birth时就会触发该注解,然后将日期进行对应的处理;

其中CustomDateSerializer.class是我们自定义的日期序列化类,如下所示:

public class CustomDateSerializer extends StdSerializer<Date> {

    private static SimpleDateFormat formatter
            = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    public CustomDateSerializer() {
        this(null);
    }

    public CustomDateSerializer(Class<Date> t) {
        super(t);
    }

    @Override
    public void serialize(
            Date value, JsonGenerator gen, SerializerProvider arg2)
            throws IOException, JsonProcessingException {
        gen.writeString(formatter.format(value));
    }
}

然后我们构造一个user对象,进行测试:

ObjectMapper objectMapper = new ObjectMapper();
User user = new User("jalon", new Date());
String s = objectMapper.writeValueAsString(user);
System.out.println(s);

输出如下:

image-20220221162345380

可以看到,日期被成功格式化;

总结

本篇介绍了三个序列化会用到的注解:

  1. @JsonGetter:覆盖已有的getter方法
  2. @JsonValue:序列化整个实例,多用来覆盖toString()方法
  3. @JsonSerialize:多用来序列化日期
0

评论区