三个注解,到底该用哪一个?别再傻傻分不清了!

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

上述图中,三个实体类中对于时间的格式化都用了不同的注解方法,写法是没问题的,但是究竟用哪个呢?是不是一个头三个大了,那么我们今天就分析分析这三个时间格式化的不同之处。

一、认识三大"时间格式化"

  1. @DateTimeFormat (Spring 的专属表单时间)

    • 来源: Spring Framework (org.springframework.format.annotation)

    • 核心任务: 专门解决 HTTP 请求中日期时间字符串如何转换成后端 Java DateLocalDateTime 等类型的问题。 简单说,就是处理入参绑定

    • 主要用处:

      • 前端通过 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 对象 (反序列化),不管后端对象怎么变成字符串返回给前端!

  2. @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 对象。"

    • 比如:

      java 复制代码
      public 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
    • 关键点:它只对 Fastjson 生效,既管序列化 (出参) 也管反序列化 (入参)。

  3. @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 序列化和反序列化这个日期字段时使用的格式、时区等。

    • 比如:

      java 复制代码
      public 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 对象 (并考虑时区)。
    • 关键点:它只对 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 库

  1. 解决前端表单或 URL 参数 (application/x-www-form-urlencoded, multipart/form-data, GET 参数) 中的日期字符串转换成后端 Java 对象的问题?

    • 果断用 @DateTimeFormat
    • 这是它的本职工作。把它贴在 Controller 方法参数对象或 @ModelAttribute 对象的日期字段上。它只负责"进"。
  2. 解决后端 Java 对象中的日期字段,在返回给前端的 JSON 中如何格式化?或者前端传过来的 JSON 请求体中的日期字符串如何解析成 Java 对象?

    • 看项目使用的 JSON 库:
      • 如果项目主要使用 Fastjson: 用 @JSONField(format = "你的格式")
      • 如果项目使用 Spring Boot 默认的 Jackson 或明确使用了 Jackson: 用 @JsonFormat(pattern = "你的格式"[, timezone = "时区"])
    • 这两个注解都既管"进"(JSON请求体->Java对象)也管"出"(Java对象->JSON响应)
  3. 一个字段既要接收表单日期,又要作为 JSON 返回?

    • 这太常见了!比如一个 User 对象,用户注册时通过表单提交生日,查询用户信息时又需要把生日以特定格式返回 JSON。
    • 解决方案:@DateTimeFormat + @JsonFormat (或 @JSONField,根据 JSON 库选) 同时使用!**
    java 复制代码
    public class User {
        @DateTimeFormat(pattern = "yyyy-MM-dd")
        @JsonFormat(pattern = "yyyy/MM/dd", timezone = "GMT+8")
        private Date birthday;
        // ... 其他字段
    }

搞清楚这三个注解的"势力范围"和"工作职责",以后处理日期格式化就能得心应手,再也不会被乱七八糟的时间格式气得抓狂了!下次同事再搞混,记得把本文甩给他看哟!

相关推荐
小羊在睡觉2 小时前
golang定时器
开发语言·后端·golang
用户21411832636023 小时前
手把手教你在魔搭跑通 DeepSeek-OCR!光学压缩 + MoE 解码,97% 精度还省 10-20 倍 token
后端
追逐时光者3 小时前
一个基于 .NET 开源、功能强大的分布式微服务开发框架
后端·.net
刘一说3 小时前
Spring Boot 启动慢?启动过程深度解析与优化策略
java·spring boot·后端
壹佰大多3 小时前
【spring如何扫描一个路径下被注解修饰的类】
java·后端·spring
间彧3 小时前
Java双亲委派模型的具体实现原理是什么?
后端
间彧3 小时前
Java类的加载过程
后端
DokiDoki之父4 小时前
Spring—注解开发
java·后端·spring
提笔了无痕4 小时前
什么是Redis的缓存问题,以及如何解决
数据库·redis·后端·缓存·mybatis
浪里行舟4 小时前
国产OCR双雄对决?PaddleOCR-VL与DeepSeek-OCR全面解析
前端·后端