@JsonFormat 只会转日期?这4个高能用法太强大了

boyanx2周前技术教程5

环境:SpringBoot3.4.2



1. 简介

@JsonFormat 是 Jackson 框架中用于精准控制数据序列化与反序列化时输出格式的注解,广泛应用于日期、时间、数值等类型的格式转换。它通过声明式配置将 Java 对象属性映射为符合业务需求的 JSON 结构,例如将 Date 类型转为 "2025-12-31" 或带时区的 "2025-12-31T23:59:59+08:00"。

尽管开发者普遍将 @JsonFormat 用于日期字段的格式化,但该注解的功能边界远不止于此。接下来,我们将介绍几个其它非常强大的功能。

准备环境

public class User {
  private Long id ;
  private String firstName;
  private String lastName;
  private Date createTime = new Date();
  // getters, settters, constructors
}

定义一个Controller接口

@RestController
@RequestMapping("/users")
public class UserController {
  @GetMapping("/{id}")
  public ResponseEntity<User> query(@PathVariable Long id) {
    return ResponseEntity.ok(new User(id, "pack", "xg", new Date())) ;
  }
}

2. 实战案例

2.1 日期格式化

在默认情况下,访问上面的接口输出结果如下:

这其中的createTime日期字段默认使用的ISO 8601 标准中的扩展格式,该格式说明:

  • 2025-04-26:日期部分(年-月-日)
  • T:日期与时间的分隔符
  • 01:47:11.428:时间部分(时:分:秒.毫秒)
  • +00:00:时区偏移量(UTC+0)

这种默认的时间展示不符合我们的习惯(yyyy-MM-dd HH:mm:ss),并且时间还差了8小时,所有我们通常会采用如下的方式解决:

  • 配置文件中定义格式及时区
spring:
  jackson:
    date-format: yyyy-MM-dd HH:mm:ss
    time-zone: GMT+8
  • 使用@JsonFormat注解
@JsonFormat(
  pattern = "yyyy-MM-dd HH:mm:ss", 
  timezone = "GMT+8")
private Date createTime = new Date();

以上2种方式都能解决问题。

2.2 控制日期格式及错误自动修复

控制日期类型以数组形式输出

@JsonFormat(shape = Shape.ARRAY, timezone = "GMT+8")
private LocalDate date = LocalDate.now();

输出结果

错误的日期自动修复

我们可以通过如下的配置让其自动修复

@JsonFormat(
  pattern = "yyyy-MM-dd HH:mm:ss"
  timezone = "GMT+8", 
  lenient = OptBoolean.TRUE)
private Date createTime = new Date();

输出结果

自动将日期修复到下一个合法的日期。

2.3 指定本地语言和类型

除了指定日期格式外,我们还可以指定序列化的地域。如果不指定该参数,就会使用默认的本地语言执行序列化:

指定本地语言

通过locale属性指定地域,我们分别指定en,zh两个地域

@JsonFormat(pattern = "yyyy MMMM dd a", locale = "en")
private Date createTime = new Date();

输出结果

输出的英文 April(四月) 和 AM(上午)

locale="zh" 输出结果:

设置类型

如果你希望日期以数字(时间戳)方式输出,那么你可以通过通过如下设置:

@JsonFormat(shape = Shape.NUMBER, timezone = "GMT+8")
private Date createTime = new Date();

输出结果

2.4 忽略大小写反序列化

我们并不能保证每次接收到的json数据格式都完全一样的,可能出现属性名称大小写规则并不统一。例如,上面User对象中的属性firstName,可能接收到如下几种情况:

  • {"firstname": "John", ...}
  • {"firstName": "John", ...}
  • {"FIRSTNAME": "John", ...}

默认情况,当出现大小写不一致情况会发生什么呢?

将firstname这里全小写时,程序并不能识别到这种属性。

在这种属性key不一样的情况,如果你希望也能正确的反序列化,那么你可以通过如下的方式配置:

@JsonFormat(
  with = JsonFormat.Feature.ACCEPT_CASE_INSENSITIVE_PROPERTIES)
public class User {}

我们通过with属性来指定忽略大小写。

2.5 处理枚举类型

我们为上的User实体对象添加如下枚举类型属性:

public enum UserStatus {
  ACTIVE("活跃", 100, true), 
  INACTIVE("不活跃", 101, false), 
  PENDING("待激活", 102, false);
  
  private final String description;
  private final int code;
  private final boolean isActive;
  UserStatus(String description, int code, boolean isActive) {
    this.description = description;
    this.code = code;
    this.isActive = isActive;
  }
  public String getDescription() {
    return description;
  }
  public int getCode() {
    return code;
  }
  public boolean isActive() {
    return isActive;
  }
}

修改User实体,添加UserStatus属性

public class User {


  private UserStatus status ;
  // ...
}

默认输出结果:

status属性肯定不是我们希望的结果,我们希望将该枚举值对应的所有信息都输出。所以,我们做如下的修改:

@JsonFormat(shape = JsonFormat.Shape.OBJECT)
public enum UserStatus {}

输出结果

我们还可以通过配置告知枚举序列化时调用toString方法。

spring:
  jackson:
    serialization:
      write-enums-using-to-string: true  

修改UserStatus

public enum UserStatus {
  // ...
  @Override
  public String toString() {
    return description + "/" + code + "/" + isActive ;
  }
}

输出结果

相关文章

还在翻找工具网站?建议一分钟在NAS部署,永久告别浏览器收藏夹

本期来介绍一个高颜值的在线工具箱——极速箱(JiSuXiang),支持Docker一键部署,可提供各种程序员必备的开发工具,帮助开发者提升编程效率。并且,ARM 架构也都可以用!挺久之前我还介绍过一个...

SpringBoot 中 Json 格式化配置

SpringBoot 针对 jackson 是自动化配置的,如果需要修改,也可以自定义配置。0x01:通过 application.yml配置属性说明:spring.jackson.date-form...

效率提升工具uTools

好久没有介绍啥提升工作效率的工具了,主要是没有遇到好的了,这一小东西通过各种插件可以提升我们的工作效率,试用了下,还不错。一 uTools是什么?uTools 非常类似我以前推荐过的Listary,就...

代码整洁大师:在线JSON压缩与格式化工具

图形开发工具,它不仅是提升工作效率,更是得力助手。图形开发学院推出的在线工具集,以其核心优势,为开发者们提供了一种全新的工作方式。 JSON压缩/格式化工具(JSON压缩/格式化 - 在线工具...

一起来做一个json格式化工具吧

说到json格式化你肯定很熟悉,毕竟压缩后的json数据基本不可读,为了方便查看,我们可以在编辑器中可以通过插件一键格式化,也可以通过一些在线工具来美化,当然,有时在开发中也会遇到json格式化的需求...

Postman 接口测试实战教程:从入门到精通,全网最全项目详解

什么是接口?为什么需要接口?因为接口能使我们的实体或者软件内部数据能够被外部进行修改、查询。从而使得内部和外部实现数据交互,所以,需要用到接口。软件接口:右称:API(application prog...

发表评论    

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。