MySQL, Oracle, Linux, 软件架构及大数据技术知识分享平台

网站首页 > 精选文章 / 正文

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

2025-06-09 22:25 huorong 精选文章 1 ℃ 0 评论

环境: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 ;
  }
}

输出结果

Tags:java jsonpath

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言