@JsonFormat 只會轉(zhuǎn)日期?這四個高能用法太強(qiáng)大了
環(huán)境:SpringBoot3.4.2
1. 簡介
@JsonFormat 是 Jackson 框架中用于精準(zhǔn)控制數(shù)據(jù)序列化與反序列化時輸出格式的注解,廣泛應(yīng)用于日期、時間、數(shù)值等類型的格式轉(zhuǎn)換。它通過聲明式配置將 Java 對象屬性映射為符合業(yè)務(wù)需求的 JSON 結(jié)構(gòu),例如將 Date 類型轉(zhuǎn)為 "2025-12-31" 或帶時區(qū)的 "2025-12-31T23:59:59+08:00"。
盡管開發(fā)者普遍將 @JsonFormat 用于日期字段的格式化,但該注解的功能邊界遠(yuǎn)不止于此。接下來,我們將介紹幾個其它非常強(qiáng)大的功能。
準(zhǔn)備環(huán)境
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. 實(shí)戰(zhàn)案例
2.1 日期格式化
在默認(rèn)情況下,訪問上面的接口輸出結(jié)果如下:
圖片
這其中的createTime日期字段默認(rèn)使用的ISO 8601 標(biāo)準(zhǔn)中的擴(kuò)展格式,該格式說明:
- 2025-04-26:日期部分(年-月-日)
- T:日期與時間的分隔符
- 01:47:11.428:時間部分(時:分:秒.毫秒)
- +00:00:時區(qū)偏移量(UTC+0)
這種默認(rèn)的時間展示不符合我們的習(xí)慣(yyyy-MM-dd HH:mm:ss),并且時間還差了8小時,所有我們通常會采用如下的方式解決:
- 配置文件中定義格式及時區(qū)
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 控制日期格式及錯誤自動修復(fù)
控制日期類型以數(shù)組形式輸出
@JsonFormat(shape = Shape.ARRAY, timezone = "GMT+8")
private LocalDate date = LocalDate.now();
輸出結(jié)果
圖片
錯誤的日期自動修復(fù)
圖片
我們可以通過如下的配置讓其自動修復(fù)
@JsonFormat(
pattern = "yyyy-MM-dd HH:mm:ss"
timezone = "GMT+8",
lenient = OptBoolean.TRUE)
private Date createTime = new Date();
輸出結(jié)果
圖片
自動將日期修復(fù)到下一個合法的日期。
2.3 指定本地語言和類型
除了指定日期格式外,我們還可以指定序列化的地域。如果不指定該參數(shù),就會使用默認(rèn)的本地語言執(zhí)行序列化:
指定本地語言
通過locale屬性指定地域,我們分別指定en,zh兩個地域
@JsonFormat(pattern = "yyyy MMMM dd a", locale = "en")
private Date createTime = new Date();
輸出結(jié)果
圖片
輸出的英文 April(四月) 和 AM(上午)
locale="zh" 輸出結(jié)果:
圖片
設(shè)置類型
如果你希望日期以數(shù)字(時間戳)方式輸出,那么你可以通過通過如下設(shè)置:
@JsonFormat(shape = Shape.NUMBER, timezone = "GMT+8")
private Date createTime = new Date();
輸出結(jié)果
2.4 忽略大小寫反序列化
我們并不能保證每次接收到的json數(shù)據(jù)格式都完全一樣的,可能出現(xiàn)屬性名稱大小寫規(guī)則并不統(tǒng)一。例如,上面User對象中的屬性firstName,可能接收到如下幾種情況:
- {"firstname": "John", ...}
- {"firstName": "John", ...}
- {"FIRSTNAME": "John", ...}
默認(rèn)情況,當(dāng)出現(xiàn)大小寫不一致情況會發(fā)生什么呢?
圖片
將firstname這里全小寫時,程序并不能識別到這種屬性。
在這種屬性key不一樣的情況,如果你希望也能正確的反序列化,那么你可以通過如下的方式配置:
@JsonFormat(
with = JsonFormat.Feature.ACCEPT_CASE_INSENSITIVE_PROPERTIES)
public class User {}
我們通過with屬性來指定忽略大小寫。
圖片
2.5 處理枚舉類型
我們?yōu)樯系腢ser實(shí)體對象添加如下枚舉類型屬性:
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實(shí)體,添加UserStatus屬性
public class User {
private UserStatus status ;
// ...
}
默認(rèn)輸出結(jié)果:
圖片
status屬性肯定不是我們希望的結(jié)果,我們希望將該枚舉值對應(yīng)的所有信息都輸出。所以,我們做如下的修改:
@JsonFormat(shape = JsonFormat.Shape.OBJECT)
public enum UserStatus {}
輸出結(jié)果:
圖片
我們還可以通過配置告知枚舉序列化時調(diào)用toString方法。
spring:
jackson:
serialization:
write-enums-using-to-string: true
修改UserStatus;
public enum UserStatus {
// ...
@Override
public String toString() {
return description + "/" + code + "/" + isActive ;
}
}
輸出結(jié)果:
圖片