先给JYM看一个项目中实体类的同一字段的不同注解

上述图中,三个实体类中对于时间的格式化都用了不同的注解方法,写法是没问题的,但是究竟用哪个呢?是不是一个头三个大了,那么我们今天就分析分析这三个时间格式化的不同之处。
一、认识三大"时间格式化"
-
@DateTimeFormat
(Spring 的专属表单时间)-
来源: Spring Framework (
org.springframework.format.annotation
) -
核心任务: 专门解决 HTTP 请求中日期时间字符串如何转换成后端 Java
Date
或LocalDateTime
等类型的问题。 简单说,就是处理入参绑定。 -
主要用处:
- 前端通过 application/x-www-form-urlencoded 或 multipart/form-data (表单提交) 传递的时间参数。
-
工作方式: 它告诉 Spring MVC:"当你在 Controller 方法参数上或者接收参数的 JavaBean 属性上看到我时,请按照我指定的格式,把前端传过来的那个时间字符串,变成对应的 Java 日期时间对象!"
-
比如:
java@PostMapping("/user") public String createUser(@ModelAttribute User user) { // ... 处理 user } public class User { @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") // 告诉Spring如何把字符串变Date private Date birthday; // ... 其他字段 }
- 假设前端表单提交了一个
birthday=2023-10-25 14:30:00
,Spring 看到@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
,就知道该用这个格式把字符串变成Date
对象塞进user.birthday
。
- 假设前端表单提交了一个
-
关键点:它只管前端字符串 -> 后端 Java 对象 (反序列化),不管后端对象怎么变成字符串返回给前端!
-
-
@JSONField
(Fastjson 的日期格式)-
来源: 阿里巴巴的 Fastjson 库 (
com.alibaba.fastjson.annotation
) -
核心任务: 专门控制 Java 对象在 使用 Fastjson 库 进行序列化 (Java对象 -> JSON字符串) 和反序列化 (JSON字符串 -> Java对象) 时,日期时间字段的格式化行为。
-
主要用处: 任何使用 Fastjson 进行 JSON 转换的场景。
- 后端接口返回 JSON 数据给前端。
- 后端接收前端发送的 JSON 请求体。
- 使用 Fastjson 进行其他对象到 JSON 的转换。
-
工作方式: 它贴在 Java 类的日期字段上,对 Fastjson 说:"序列化这个字段成 JSON 时,请按 format指定的格式输出字符串;反序列化 JSON 字符串到这个字段时,也请按
format
指定的格式去解析成 Date 对象。" -
比如:
javapublic class Order { @JSONField(format = "yyyy-MM-dd HH:mm") // 告诉Fastjson怎么序列化和反序列化 private Date createTime; // ... 其他字段 }
- 序列化 (后端 -> 前端 JSON): order.createTime 是一个
Date
对象,Fastjson 会按 "yyyy-MM-dd HH:mm" 格式把它变成字符串,如 "2023-10-25 14:30" 写入 JSON。 - 反序列化 (前端 JSON -> 后端): 如果前端 POST 一个 JSON 过来 {"createTime": "2023-10-25 14:30"}, Fastjson 会按 "yyyy-MM-dd HH:mm" 格式把这个字符串解析成
Date
对象,塞进order.createTime
。
- 序列化 (后端 -> 前端 JSON): order.createTime 是一个
-
关键点:它只对 Fastjson 生效,既管序列化 (出参) 也管反序列化 (入参)。
-
-
@JsonFormat
(Jackson 的日期格式)-
老家: Jackson 库 (
com.fasterxml.jackson.annotation
) -
核心任务: 专门控制 Java 对象在 使用 Jackson 库 (Spring Boot 默认使用它!) 进行序列化 (Java对象 -> JSON字符串) 和反序列化 (JSON字符串 -> Java对象) 时,日期时间字段的格式化行为。 功能上和
@JSONField
非常相似,只是服务的库不同。 -
主要用处: 任何使用 Jackson 进行 JSON 转换的场景 (尤其在 Spring Boot 项目中非常普遍)。
- @RestController 返回的对象自动转 JSON。
- 接收 @RequestBody 注解的 JSON 参数。
- 使用 ObjectMapper 进行手动 JSON 转换。
-
工作方式: 和
@JSONField
几乎一样,贴在字段上,告诉 Jackson 序列化和反序列化这个日期字段时使用的格式、时区等。 -
比如:
javapublic class Product { @JsonFormat(pattern = "yyyy/MM/dd", timezone = "GMT+8") // 告诉Jackson private Date expiryDate; // ... 其他字段 }
- 序列化 (后端 -> 前端 JSON): Jackson 会把
product.expiryDate
按"yyyy/MM/dd"
格式和东八区时区输出,如"2024/12/31"
。 - 反序列化 (前端 JSON -> 后端): 前端传
{"expiryDate": "2024/12/31"}
, Jackson 会按"yyyy/MM/dd"
格式解析成Date
对象 (并考虑时区)。
- 序列化 (后端 -> 前端 JSON): Jackson 会把
-
关键点:它只对 Jackson 生效,是 Spring Boot 生态下的 JSON 格式化主力,既管序列化也管反序列化。
-
二、对照表看吧就
特性 | @DateTimeFormat (Spring) |
@JSONField (Fastjson) |
@JsonFormat (Jackson) |
---|---|---|---|
所属库/框架 | Spring Framework | 阿里巴巴 Fastjson | FasterXML Jackson |
主要职责 | 入参绑定 (字符串 -> Date) | JSON 序列化与反序列化 | JSON 序列化与反序列化 |
作用方向 | 单向 (仅入参反序列化) | 双向 (序列化 + 反序列化) | 双向 (序列化 + 反序列化) |
关键场景 | 表单提交 / URL 查询参数 | 使用 Fastjson 处理 JSON 的接口 | 使用 Jackson (Spring Boot默认) 处理 JSON 的接口 |
常用属性 | pattern (格式) |
format (格式), name (别名) 等 |
pattern (格式), timezone (时区), locale (地区) 等 |
是否处理出参 | 否 | 是 | 是 |
是否处理入参 | 是 (仅特定来源) | 是 (JSON 请求体) | 是 (JSON 请求体) |
三、到底该用谁?
选择的关键在于弄清楚你当前要解决的是什么问题 ,以及你的项目用了哪个 JSON 库:
-
解决前端表单或 URL 参数 (application/x-www-form-urlencoded, multipart/form-data, GET 参数) 中的日期字符串转换成后端 Java 对象的问题?
- 果断用 @DateTimeFormat
- 这是它的本职工作。把它贴在 Controller 方法参数对象或 @ModelAttribute 对象的日期字段上。它只负责"进"。
-
解决后端 Java 对象中的日期字段,在返回给前端的 JSON 中如何格式化?或者前端传过来的 JSON 请求体中的日期字符串如何解析成 Java 对象?
- 看项目使用的 JSON 库:
- 如果项目主要使用 Fastjson: 用
@JSONField(format = "你的格式")
。 - 如果项目使用 Spring Boot 默认的 Jackson 或明确使用了 Jackson: 用
@JsonFormat(pattern = "你的格式"[, timezone = "时区"])
。
- 如果项目主要使用 Fastjson: 用
- 这两个注解都既管"进"(JSON请求体->Java对象)也管"出"(Java对象->JSON响应)。
- 看项目使用的 JSON 库:
-
一个字段既要接收表单日期,又要作为 JSON 返回?
- 这太常见了!比如一个
User
对象,用户注册时通过表单提交生日,查询用户信息时又需要把生日以特定格式返回 JSON。 - 解决方案:@DateTimeFormat + @JsonFormat (或
@JSONField
,根据 JSON 库选) 同时使用!**
javapublic class User { @DateTimeFormat(pattern = "yyyy-MM-dd") @JsonFormat(pattern = "yyyy/MM/dd", timezone = "GMT+8") private Date birthday; // ... 其他字段 }
- 这太常见了!比如一个
搞清楚这三个注解的"势力范围"和"工作职责",以后处理日期格式化就能得心应手,再也不会被乱七八糟的时间格式气得抓狂了!下次同事再搞混,记得把本文甩给他看哟!