@JsonFormat 只会转日期?这4个高能用法太强大了
环境:SpringBoot3.4.2
1. 简介
@JsonFormat 是 Jackson 框架中用于精准控制数据序列化与反序列化时输出格式的注解,广泛应用于日期、时间、数值等类型的格式转换。它通过声明式配置将 Java 对象属性映射为符合业务需求的 JSON 结构,例如将 Date 类型转为 "2025-12-31" 或带时区的 "2025-12-31T23:59:59+08:00"。
尽管开发者普遍将 @JsonFormat 用于日期字段的格式化,但该注解的功能边界远不止于此。接下来,我们将介绍几个其它非常强大的功能。
准备环境
public class User {
private Long id ;
private String firstName;
private String lastName;
private Date createTime = new Date();
// getters, settters, constructors
}
定义一个Controller接口
@RestController
@RequestMapping("/users")
public class UserController {
@GetMapping("/{id}")
public ResponseEntity<User> query(@PathVariable Long id) {
return ResponseEntity.ok(new User(id, "pack", "xg", new Date())) ;
}
}
2. 实战案例
2.1 日期格式化
在默认情况下,访问上面的接口输出结果如下:
这其中的createTime日期字段默认使用的ISO 8601 标准中的扩展格式,该格式说明:
- 2025-04-26:日期部分(年-月-日)
- T:日期与时间的分隔符
- 01:47:11.428:时间部分(时:分:秒.毫秒)
- +00:00:时区偏移量(UTC+0)
这种默认的时间展示不符合我们的习惯(yyyy-MM-dd HH:mm:ss),并且时间还差了8小时,所有我们通常会采用如下的方式解决:
- 配置文件中定义格式及时区
spring:
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
- 使用@JsonFormat注解
@JsonFormat(
pattern = "yyyy-MM-dd HH:mm:ss",
timezone = "GMT+8")
private Date createTime = new Date();
以上2种方式都能解决问题。
2.2 控制日期格式及错误自动修复
控制日期类型以数组形式输出
@JsonFormat(shape = Shape.ARRAY, timezone = "GMT+8")
private LocalDate date = LocalDate.now();
输出结果
错误的日期自动修复
我们可以通过如下的配置让其自动修复
@JsonFormat(
pattern = "yyyy-MM-dd HH:mm:ss"
timezone = "GMT+8",
lenient = OptBoolean.TRUE)
private Date createTime = new Date();
输出结果
自动将日期修复到下一个合法的日期。
2.3 指定本地语言和类型
除了指定日期格式外,我们还可以指定序列化的地域。如果不指定该参数,就会使用默认的本地语言执行序列化:
指定本地语言
通过locale属性指定地域,我们分别指定en,zh两个地域
@JsonFormat(pattern = "yyyy MMMM dd a", locale = "en")
private Date createTime = new Date();
输出结果
输出的英文 April(四月) 和 AM(上午)
locale="zh" 输出结果:
设置类型
如果你希望日期以数字(时间戳)方式输出,那么你可以通过通过如下设置:
@JsonFormat(shape = Shape.NUMBER, timezone = "GMT+8")
private Date createTime = new Date();
输出结果
2.4 忽略大小写反序列化
我们并不能保证每次接收到的json数据格式都完全一样的,可能出现属性名称大小写规则并不统一。例如,上面User对象中的属性firstName,可能接收到如下几种情况:
- {"firstname": "John", ...}
- {"firstName": "John", ...}
- {"FIRSTNAME": "John", ...}
默认情况,当出现大小写不一致情况会发生什么呢?
将firstname这里全小写时,程序并不能识别到这种属性。
在这种属性key不一样的情况,如果你希望也能正确的反序列化,那么你可以通过如下的方式配置:
@JsonFormat(
with = JsonFormat.Feature.ACCEPT_CASE_INSENSITIVE_PROPERTIES)
public class User {}
我们通过with属性来指定忽略大小写。
2.5 处理枚举类型
我们为上的User实体对象添加如下枚举类型属性:
public enum UserStatus {
ACTIVE("活跃", 100, true),
INACTIVE("不活跃", 101, false),
PENDING("待激活", 102, false);
private final String description;
private final int code;
private final boolean isActive;
UserStatus(String description, int code, boolean isActive) {
this.description = description;
this.code = code;
this.isActive = isActive;
}
public String getDescription() {
return description;
}
public int getCode() {
return code;
}
public boolean isActive() {
return isActive;
}
}
修改User实体,添加UserStatus属性
public class User {
private UserStatus status ;
// ...
}
默认输出结果:
status属性肯定不是我们希望的结果,我们希望将该枚举值对应的所有信息都输出。所以,我们做如下的修改:
@JsonFormat(shape = JsonFormat.Shape.OBJECT)
public enum UserStatus {}
输出结果
我们还可以通过配置告知枚举序列化时调用toString方法。
spring:
jackson:
serialization:
write-enums-using-to-string: true
修改UserStatus
public enum UserStatus {
// ...
@Override
public String toString() {
return description + "/" + code + "/" + isActive ;
}
}
输出结果