【深度思考】自定义日期格式,为什么@JSONField生效,@JsonFormat不生效? ...

瑞星  论坛元老 | 2025-4-21 09:35:50 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 1830|帖子 1830|积分 5490

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
1. 媒介

最近在自测接口时,发现一个题目:字段范例定义的是Date,但接口返回值里却是时间戳(1744959978674),
而不是预期的2025-04-18 15:06:18。
  1. private Date useTime;
复制代码
  1. {
  2.     "code": "200",
  3.     "message": "",
  4.     "result": [
  5.         {
  6.             "id": 93817601,
  7.             "useTime": 1744959978674
  8.         }
  9.     ]
  10. }
复制代码
这种返回值,无法快速的知道是哪个时间,如果想知道时间对不对,还得找一个时间戳转换工具做下转换才华确定,非常不方便。
因此想让接口直接返回预期的2025-04-18 15:06:18格式。
刚开始,在字段上添加了@JsonFormat注解,发现没生效,返回的还是时间戳:
  1. import com.fasterxml.jackson.annotation.JsonFormat;
  2. @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss")
  3. private Date useTime;
复制代码
然后,改成了@JSONField注解,发现生效了,到达了预期的效果:
  1. import com.alibaba.fastjson.annotation.JSONField;
  2. @JSONField(format = "yyyy-MM-dd HH:mm:ss")
  3. private Date useTime;
复制代码
  1. {
  2.     "code": "200",
  3.     "message": "",
  4.     "result": [
  5.         {
  6.             "id": 93817601,
  7.             "useTime": "2025-04-18 15:06:18"
  8.         }
  9.     ]
  10. }
复制代码
那么题目来了,为啥@JSONField生效,@JsonFormat不生效?
2. 原因分析

默认情况下,Spring Boot利用的JSON消息转换器是Jackson的MappingJackson2HttpMessageConverter,焦点依赖为:
  1. <dependency>
  2.     <groupId>com.fasterxml.jackson.core</groupId>
  3.     <artifactId>jackson-databind</artifactId>
  4.     <version>2.8.11.3</version>
  5. </dependency>
复制代码
现在利用Jackson的@JsonFormat注解不生效,说明Spring Boot没有利用默认的MappingJackson2HttpMessageConverter。
利用fastjson的@JSONField注解生效了,说明Spring Boot利用的是fastjson下的JSON消息转换器,也就是
FastJsonHttpMessageConverter,依赖为:
  1. <dependency>
  2.     <groupId>com.alibaba</groupId>
  3.     <artifactId>fastjson</artifactId>
  4.     <version>1.2.83</version>
  5. </dependency>
复制代码
那么怎么找到代码在哪设置的呢?
第一步,先在项目中全局搜索FastJsonHttpMessageConverter(Windows快捷键:Ctrl+Shift+F),不外大概率是搜索不到,由于
公司里的项目一般都继承自公司公共的xxx-spring-boot-starter。
第二步,连按2次Shift键搜索FastJsonHttpMessageConverter,然后查找该类的引用或者子类(子类很可能是公司底层框架中写的)。
然后,很可能会找到雷同下面的代码:
  1. @Configuration
  2. public class FastJsonMessageConverterConfig {
  3.     @Bean
  4.     public HttpMessageConverters customConverters() {
  5.         FastJsonHttpMessageConverter fastJsonHttpMessageConverter = new FastJsonHttpMessageConverter();
  6.         return new HttpMessageConverters(new HttpMessageConverter[]{fastJsonHttpMessageConverter});
  7.     }
  8. }
复制代码
以上代码显式注册了一个FastJsonHttpMessageConverter,并通过HttpMessageConverters覆盖了默认的HTTP 消息转换器
(Jackson的MappingJackson2HttpMessageConverter),以是Spring MVC将只利用fastjson处理JSON序列化/反序列化。
这也是@JSONField生效,@JsonFormat不生效的根本原因。
3. 默认行为及全局设置

fastjson 1.2.36及以上版本,默认将日期序列化为时间戳(如1744959978674),如果要默认将日期序列化为yyyy-MM-dd HH:mm:ss
(如2025-04-18 15:06:18),需要启用WriteDateUseDateFormat特性:
  1. @Configuration
  2. public class FastJsonMessageConverterConfig {
  3.     @Bean
  4.     public HttpMessageConverters customConverters() {
  5.         FastJsonConfig fastJsonConfig = new FastJsonConfig();
  6.         // 启用日期格式化特性(禁用时间戳)
  7.                    fastJsonConfig.setSerializerFeatures(SerializerFeature.WriteDateUseDateFormat);
  8.         // 设置日期格式(不指定时,默认为yyyy-MM-dd HH:mm:ss,但即使与默认值一致,也建议明确指定)
  9.             fastJsonConfig.setDateFormat("yyyy-MM-dd HH:mm:ss");
  10.         
  11.         FastJsonHttpMessageConverter fastJsonHttpMessageConverter = new FastJsonHttpMessageConverter();
  12.         fastJsonHttpMessageConverter.setFastJsonConfig(fastJsonConfig);
  13.         return new HttpMessageConverters(new HttpMessageConverter[]{fastJsonHttpMessageConverter});
  14.     }
  15. }
复制代码
如果某个日期字段有特殊序列化要求,可以利用@JSONField注解机动设置(该注解会覆盖全局设置):
  1. import com.alibaba.fastjson.annotation.JSONField;
  2. @JSONField(format = "yyyy-MM-dd")
  3. private Date anotherUseTime;
复制代码
注意事项:
修改全局设置需慎重,如果一个老项目,原来日期范例返回的都是时间戳,突然全部改为返回字符串,可能会造成调用方报错。
文章连续更新,欢迎关注微信公众号「申城他乡人」第一时间阅读!

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

瑞星

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表