当前位置: 首页 > news >正文

@DateTimeFormat 与 @JsonFormat 详解

@DateTimeFormat 与 @JsonFormat 详解

适用场景:Spring Boot + Jackson 项目中的时间类型参数处理


一、概述

在 Spring Boot 项目中,处理时间类型(LocalDateTimeDate等)时,开发者常常遇到两个注解:

  • @DateTimeFormat:来自 Spring 框架
  • @JsonFormat:来自 Jackson 框架

两者职责不同、作用时机不同,混用或单用都可能导致时间解析失败。本文将系统梳理两者的区别与最佳实践。


二、@DateTimeFormat — 入参解析印

2.1 基本信息

属性说明
归属org.springframework.format.annotation
框架Spring MVC
职责将 HTTP 请求入参中的字符串 → 时间对象

2.2 适用场景

场景是否生效
@RequestParam查询参数✅ 生效
@ModelAttribute表单提交✅ 生效
实体类字段(Form 提交)✅ 生效
@RequestBodyJSON 字段不生效(由 Jackson 处理)

2.3 使用示例

// GET /user/list?createTime=2024-01-15 10:30:00@GetMapping("/list")publicApiResult<List<UserVO>>list(@RequestParam@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")LocalDateTimecreateTime){// ...}
@DatapublicclassUserQueryDTO{// Form 表单提交时,Spring MVC 会按此格式解析字符串@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")privateLocalDateTimestartTime;}

三、@JsonFormat — JSON 序列化/反序列化印

3.1 基本信息

属性说明
归属com.fasterxml.jackson.annotation
框架Jackson
职责控制 JSON序列化(对象 → 字符串)与反序列化(字符串 → 对象)的格式

3.2 适用场景

场景是否生效
@RequestBodyJSON 反序列化✅ 生效
@ResponseBodyJSON 序列化(响应输出)✅ 生效
@RequestParam查询参数不生效
Form 表单提交不生效

3.3 使用示例

@DatapublicclassUserVO{// 序列化输出 + JSON 反序列化输入,均按此格式处理@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone="Asia/Shanghai")privateLocalDateTimecreateTime;}

3.4 重要参数说明

参数说明示例
pattern时间格式"yyyy-MM-dd HH:mm:ss"
timezone时区(不指定可能导致时间偏移 8 小时)"Asia/Shanghai"/"GMT+8"
shape序列化形状JsonFormat.Shape.STRING

四、核心对比

维度@DateTimeFormat@JsonFormat
归属框架Spring MVCJackson
作用方向入参解析(String → Date)序列化 + 反序列化
适用场景Form / Query 参数JSON Body 入参 + 响应输出
时区参数❌ 无timezone
生效位置方法参数、字段字段、getter/setter

五、最佳实践:双印加持

对于实体类/DTO 字段,同时加上两个注解,覆盖所有入参场景:

@DatapublicclassProjectPageDTO{/** * 开始时间 * - @DateTimeFormat:处理 Query/Form 入参(Spring MVC 解析) * - @JsonFormat:处理 JSON Body 入参 + 响应输出(Jackson 处理) */@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone="Asia/Shanghai")privateLocalDateTimestartTime;@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone="Asia/Shanghai")privateLocalDateTimeendTime;}

六、全局配置(更优解)

在 Spring Boot 项目中,可通过全局 Jackson 配置统一处理序列化格式,避免在每个字段上重复添加@JsonFormat

6.1 全局 Jackson 配置

@ConfigurationpublicclassJacksonConfig{@BeanpublicJackson2ObjectMapperBuilderCustomizerjsonCustomizer(){returnbuilder->{// 全局时区builder.timeZone(TimeZone.getTimeZone("Asia/Shanghai"));// LocalDateTime 序列化格式builder.serializers(newLocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));// LocalDateTime 反序列化格式builder.deserializers(newLocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));};}}

6.2 全局配置后的使用策略

场景是否需要注解
普通时间字段,格式与全局一致❌ 无需添加@JsonFormat
特殊格式字段(如只需日期yyyy-MM-dd✅ 需要单独加@JsonFormat覆盖
Query 参数(所有场景)✅ 仍需手动加@DateTimeFormat

七、常见陷阱

陷阱一:仅加 @JsonFormat,Query 参数报错

// ❌ GET 请求传参时解析失败@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss")privateLocalDateTimecreateTime;

错误信息Failed to convert value of type 'String' to required type 'LocalDateTime'

陷阱二:仅加 @DateTimeFormat,JSON Body 格式不受控

// ❌ JSON 入参和响应依赖全局 Jackson 配置,字段级别无法控制格式@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")privateLocalDateTimecreateTime;

陷阱三:@JsonFormat 未指定 timezone 导致时间偏移

// ❌ 可能导致时间偏移 8 小时(UTC vs Asia/Shanghai)@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss")privateLocalDateTimecreateTime;// ✅ 明确指定时区@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone="Asia/Shanghai")privateLocalDateTimecreateTime;

陷阱四:两个注解的 pattern 不一致

// ❌ 格式不统一,不同入参方式解析结果不同,难以排查@DateTimeFormat(pattern="yyyy-MM-dd")@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone="Asia/Shanghai")privateLocalDateTimecreateTime;

八、完整代码示例

以下是一个涵盖各场景的完整示例:

/** * 项目分页查询 DTO */@DatapublicclassProjectPageDTO{/** 项目名称(模糊搜索) */privateStringprojectName;/** * 创建时间起(双印加持) * Query 参数 + JSON Body 均支持 */@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone="Asia/Shanghai")privateLocalDateTimecreateTimeStart;/** * 创建时间止 */@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone="Asia/Shanghai")privateLocalDateTimecreateTimeEnd;}
/** * 项目响应 VO */@DatapublicclassProjectVO{privateLongprojectId;privateStringprojectName;/** * 创建时间 * 全局 JacksonConfig 已配置默认格式时,此注解可省略 * 需要特殊格式时才单独加 */@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone="Asia/Shanghai")privateLocalDateTimecreateTime;}

九、总结

HTTP 请求 │ ┌─────────┴─────────┐ │ │ Query/Form JSON Body │ │ @DateTimeFormat @JsonFormat (Spring MVC 解析) (Jackson 解析) │ │ └─────────┬─────────┘ │ 时间对象 ✅
注解核心职责一句话记忆
@DateTimeFormatQuery/Form 入参解析“URL 和表单用我”
@JsonFormatJSON 序列化/反序列化“JSON 进出用我”

最佳实践

  1. 全局配置JacksonConfig统一 JSON 时间格式与时区
  2. 所有时间类型字段标注@DateTimeFormat,覆盖 Query 参数场景
  3. 仅在需要特殊格式时,才在字段上单独加@JsonFormat覆盖全局配置

本文基于 Spring Boot 2.7.x + Jackson 2.13.x 编写,适用于 Java 8+ 项目。

http://www.jsqmd.com/news/1277754/

相关文章:

  • 拓竹A1C 3D打印机:工科生高速打印入门指南与项目实践
  • 数学建模优化水系电解液配方的核心方法与工程实践
  • 铌酸锂LNOI法诺共振仿真与优化实践
  • 微软Build 2026:Windows原生支持AI智能体,开启操作系统新范式
  • Python项目代码骨架构建与目标函数设计实践
  • Python模拟DDoS攻击与防御:本地实验环境搭建与原理剖析
  • 从滁州出发西藏,怎么选靠谱旅行社?这份避坑攻略(含西藏研学旅行社推荐)| 附:旅行社电话 - 西藏康泰旅行社
  • AI绘画工作流优化:infinite-canvas本地部署与批量出图实战
  • Obsidian模板终极指南:17个免费模板3分钟打造高效知识管理系统
  • BlackHole免费终极指南:3步解锁macOS音频魔法,彻底告别音频孤岛
  • ComfyUI+Wan2.2:AI视频生成工作流部署与电影级镜头实战
  • TPIC7710EVM评估板实战指南:从安全操作到电机驱动验证
  • 数据分析自学指南:从Excel到Python的完整技能栈与实战路径
  • 核心期刊投稿AI率卡在28%怎么办?免费3步压到10%以内,CSSCI北大核心亲测达标
  • 深度解析Qwen Code:5步实现AI编程助手的终极VS Code集成方案
  • Spring Boot设计模式实战:工厂与单例模式解析
  • Kimi LeetCode 3748. 统计稳定子数组的数目 Java实现
  • PlayIntegrityFix完整指南:解决Android设备Play Integrity认证问题的终极方案
  • DeepSWE基准测试解析:GPT-5.6 Sol与Opus 5在软件工程任务中的表现对比
  • ZotMoov 终极指南:如何高效管理 Zotero 附件,释放文献库空间
  • 2026盘点:于晓昆律师领衔的专业潍坊股权架构法律服务解析 - 装修教育财税推荐2026
  • GmSSL3配置SM2双证书全攻略:从编译到实战的避坑指南
  • PCIe-3.4/3.4.1 Flow Control Initialization Protocol-fc Initialization State Machine Rules(initFC1)
  • 转湾流水线定制厂家哪个性价比高:升级 - 品牌推广大师
  • LangGraph实战:构建高效多智能体协作系统
  • 如何零代码构建企业级数据洞察:Metabase开源BI工具完整实践指南
  • 5步搞定Switch手柄在PC游戏中的完美体验:BetterJoy配置全攻略
  • 终极指南:如何用CKAN一键管理你的坎巴拉太空计划模组库
  • 智能文本降重工具评测与核心技术解析
  • HarmonyOS应用开发实战:猫猫大作战-在 HarmonyOS 应用中,首屏加载速度是用户体验的关键指标