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

目 录CONTENT

文章目录

Jackson处理日期

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

前言

Jackson处理日期有多种方式,不同的日期类型有不同的处理方式;

下面就分别介绍下Date、LocalDate的处理方法;

目录

  1. Date的处理
  2. LocalDate的处理
  3. 两者的反序列化处理

正文

1. Date的处理

这里的Date指的是 java.util.Date;

1. 默认行为:

我们先看下默认的Jackson是怎么处理Date的;

下面是User实体类,包含一个Date类型的birth字段:

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.Date;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {

    private String username;

    private Date birth;

}

下面是主程序方法:

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

输出如下:

image-20220216153710021

可以看到,默认的处理就是把日期转为时间戳;

2. 字段加注解@JsonFormat:

我们可以在字段上加@JsonFormat注解来处理Date日期,如下所示:

@JsonFormat(pattern = "yyyy-MM-dd")
private Date birth;

此时运行输出如下:

image-20220216154120820

这里的JsonFormat注解只针对序列化有效,在反序列化时无效;

注意时区问题,如果精确到小时,需添加时区配置:

@JsonFormat( pattern="yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")

3. 字段加注解@JsonSerialize:

上面的@JsonFormat每用一次,就需要写一个日期的格式(yyyy-MM-dd);

这里可以自己定义一个全局的序列化类,然后在需要序列化的字段上通过@JsonSerialize直接引用该类即可,这样可以保持全局统一;

自定义的日期序列化类如下所示:

public class CustomDateSerializer extends StdSerializer<Date> {

    private SimpleDateFormat formatter
            = new SimpleDateFormat("yyyy-MM-dd");

    public CustomDateSerializer() {
        this(null);
    }

    public CustomDateSerializer(Class t) {
        super(t);
    }

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

然后在对应的字段加@JsonSerialize注解:

@JsonSerialize(using = CustomDateSerializer.class)
private Date birth;

运行后可以看到输出符合设定的日期格式;

4. 配置ObjectMapper:

这个类似上面的自定义类,都相当于全局配置;

不过这个是非侵入的,不需要修改实体类;

配置如下:

SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setDateFormat(dateFormat);

此时就可以实现和上面一样的效果;

2. LocalDate的处理

LocalDate属于Java8新增的日期类,处理方式跟Date稍有不同;

LocalDate的处理有两种方式,一种是添加外部依赖,一种是字段加注解@JsonSerialize

1. 添加外部依赖:

这种方式不需要我们自己定义日期序列化类,依赖中有包含,我们只需要引入并注册即可;

实体类User的birth改为LocalDate类型:

private LocalDate birth;

添加依赖如下:

<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-jsr310</artifactId>
    <version>2.12.5</version>
</dependency>

主程序中注册对应的Java8日期模块,并禁用默认的日期转时间戳:

User user = new User("jalon", LocalDateTime.now());
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new JavaTimeModule());
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
String s = objectMapper.writeValueAsString(user);
System.out.println(s);

输出如下:

image-20220216161553958

可以看到,我们全程没有设置日期的格式化,但是输出也是符合预期;

这是因为注册的JavaTimeModule已经帮我们提前配置好了,它会根据日期的类型(比如LocalDate或者LocalDateTime)自动选择默认的格式进行处理,这里就是根据LocalDate选择了yyyy-MM-dd格式;

image-20220216161828255

同时支持序列化和反序列化

2. 字段加注解@JsonSerialize:

当然如果觉得添加依赖太麻烦,可以跟Date一样,自己定义一个日期序列化类,然后通过@JsonSerialize指向定义的类即可;

自定义的类如下:

public class CustomDateSerializer2 extends StdSerializer<LocalDate> {

    private DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");

    public CustomDateSerializer2() {
        this(null);
    }

    public CustomDateSerializer2(Class t) {
        super(t);
    }

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

这里跟Date自定义的日期序列化类不同的地方,就是日期格式化的类不一样,这里是DateTimeFormatter(前面是SimpleDateFormatter);

User实体类的birth字段添加@JsonSerialize注解:

@JsonSerialize(using = CustomDateSerializer2.class)
private LocalDate birth;

运行后跟上面一样的效果;

3. 两者的反序列化处理

Date类型的反序列化处理,只能取出对象的日期值后,再通过SimpleDateFormat处理;

User user1 = objectMapper.readerFor(User.class).readValue(s);
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
System.out.println(dateFormat.format(user1.getBirth()));

LocalDate类型的反序列化,可以通过添加依赖的方式进行处理,依赖的相关操作见上添加外部依赖

总结

Date有多种方式可以实现日期的处理,我们只需要根据自己的需要,选择一种即可,比如@JsonFormat

LocalDate的话一般用添加依赖的方式就够用了,这样的话序列化和反序列化都支持;

其实不管是Date还是LocalDate,都可以通过@JsonSerialize注解+自定义的日期序列化类来实现日期的相关处理;

0

评论区