@jsonformat注解不生效主因是objectmapper未配置时区及缺失javatimemodule:需调用settimezone(timezone.gettimezone("asia/shanghai"))并注册javatimemodule,且pattern须匹配java.time类型规则。

JsonFormat注解不生效?检查是否漏了 ObjectMapper 的时区配置
Java 用 @JsonFormat 标注字段后,JSON 输出仍是时间戳或格式不对,大概率不是注解写错了,而是 ObjectMapper 没配默认时区。Jackson 默认用系统本地时区解析/序列化,但 @JsonFormat 只控制单字段格式,不接管时区逻辑——它依赖 ObjectMapper 的全局时区设置才能稳定输出预期字符串。
-
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")中的timezone属性只在反序列化(JSON → Java)时生效;序列化(Java → JSON)仍走ObjectMapper的setTimeZone() - Spring Boot 项目需在配置类中显式设置:
objectMapper.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai")) - 纯 Jackson 环境下,构造
ObjectMapper后必须立即调用setTimeZone(),否则即使字段加了@JsonFormat,输出也可能变成 UTC 时间或带 Z 后缀
pattern 写错导致抛出 JsonMappingException
常见错误是把 Java 的 SimpleDateFormat 模式和 Java 8 的 DateTimeFormatter 混用。Jackson 2.9+ 默认使用 java.time 类型(如 LocalDateTime、ZonedDateTime),此时 @JsonFormat(pattern = "...") 必须符合 DateTimeFormatter 规则,而非老式 SimpleDateFormat。
- 错误写法:
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")—— 对LocalDateTime有效,但对Date或Calendar会失败(因 Jackson 2.9+ 已弃用对老日期类的 pattern 支持) - 正确写法:用
LocalDateTime+@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss");若必须用Date,改用@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")并确保ObjectMapper注册了JavaTimeModule - 注意大小写:
MM是月,mm是分;HH是24小时制,hh是12小时制——写错会导致输出全为 00 或解析失败
LocalDateTime 序列化为空对象 {}?缺 JavaTimeModule
用 LocalDateTime 字段加 @JsonFormat,结果 JSON 里该字段直接消失或变成空对象 {},基本等于没注册 JavaTimeModule。Jackson 默认不支持 java.time 类型,必须手动注册模块,否则连基本序列化都失败。
- Spring Boot 2.0+ 默认已注册,但若自定义了
ObjectMapperBean,必须显式添加:objectMapper.registerModule(new JavaTimeModule()) - 非 Spring 环境下,new 完
ObjectMapper后第一件事就是registerModule(new JavaTimeModule()) - 别用
SimpleModule替代——它不包含LocalDateTimeSerializer,补也白补
时区偏移量(+0800)和区域 ID(Asia/Shanghai)混用出问题
@JsonFormat(timezone = "...") 里的值不是随便填的。填 "GMT+8" 和填 "Asia/Shanghai" 行为不同:前者是固定偏移,后者会随夏令时动态调整(虽然中国不用夏令时,但其他地区会)。更关键的是,Jackson 对这两类字符串的解析路径不同,填错可能静默失效。
立即学习“Java免费学习笔记(深入)”;
- 推荐统一用区域 ID:
timezone = "Asia/Shanghai",和ObjectMapper.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"))保持一致 - 避免用
"GMT+8"或"UTC+8"——Jackson 有些版本会忽略这类写法,且无法处理历史时区变更(比如 1986 年前上海用 UTC+8:06) - 如果服务部署在 Docker 容器里,还要确认容器内时区文件完整(
/usr/share/zoneinfo/Asia/Shanghai存在),否则TimeZone.getTimeZone("Asia/Shanghai")可能退化成 GMT










