前言
Jackson处理日期有多种方式,不同的日期类型有不同的处理方式;
下面就分别介绍下Date、LocalDate的处理方法;
目录
- Date的处理
- LocalDate的处理
- 两者的反序列化处理
正文
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);
输出如下:
可以看到,默认的处理就是把日期转为时间戳;
2. 字段加注解@JsonFormat:
我们可以在字段上加@JsonFormat注解来处理Date日期,如下所示:
@JsonFormat(pattern = "yyyy-MM-dd")
private Date birth;
此时运行输出如下:
这里的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);
输出如下:
可以看到,我们全程没有设置日期的格式化,但是输出也是符合预期;
这是因为注册的JavaTimeModule已经帮我们提前配置好了,它会根据日期的类型(比如LocalDate或者LocalDateTime)自动选择默认的格式进行处理,这里就是根据LocalDate选择了yyyy-MM-dd
格式;
同时支持序列化和反序列化
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注解+自定义的日期序列化类来实现日期的相关处理;
评论区