@JsonCreator 注解详解——从枚举反序列化说起

@JsonCreator 注解详解------从枚举反序列化说起

一、问题的起源

先看这段实际代码:

java 复制代码
public enum SectionType implements BaseEnum {
    VIDEO(1, "视频"),
    EXAM(2, "考试"),
    ;
	@JsonValue
    @EnumValue
    int value;
    String desc;

    SectionType(int value, String desc) {
        this.value = value;
        this.desc = desc;
    }

    @JsonCreator(mode = JsonCreator.Mode.DELEGATING)
    public static SectionType of(Integer value){
        if (value == null) return null;
        for (SectionType status : values()) {
            if (status.equalsValue(value)) return status;
        }
        return null;
    }
}

前端传数字 1,后端自动变成 VIDEO 枚举------这个"自动变"的背后,就是 @JsonCreator 在起作用。


二、为什么需要它?

默认情况下的问题

没有这个注解时,Jackson 反序列化枚举默认用的是枚举名

json 复制代码
// 前端只能这么传
{ "type": "VIDEO" }    ✅ 能解析成 SectionType.VIDEO
{ "type": "video" }    ❌ 报错(大小写不匹配)
{ "type": 1 }          ❌ 报错(类型不匹配)

但实际开发中,前端更习惯传数字(比如 1 表示视频、2 表示考试),或者数据库里存的就是数字。所以需要告诉 Jackson:"别用枚举名来匹配,按我自定义的方法来。"


三、@JsonCreator 的两个核心模式

DELEGATING(委托模式)------ 整体传入

java 复制代码
@JsonCreator(mode = JsonCreator.Mode.DELEGATING)
public static SectionType of(Integer value) { ... }

含义:把整个 JSON 值当成一个整体,直接丢给这个方法。

复制代码
JSON 传入 1  →  Jackson 调用 of(1)  →  返回 SectionType.VIDEO
JSON 传入 2  →  Jackson 调用 of(2)  →  返回 SectionType.EXAM

形象类比:就像快递员把整个箱子递给你,你不需要当着面拆箱核对清单,自己拎到屋里打开看一眼就知道是什么东西。

PROPERTIES(属性模式)------ 拆箱核对

java 复制代码
@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
public static SectionType of(int value, String desc) { ... }

含义:把 JSON 对象拆开,按属性名一一匹配到方法参数。

json 复制代码
JSON 传入 {"value":1, "desc":"视频"}  →  of(1, "视频")  →  SectionType.VIDEO

形象类比:快递员让你当面拆箱,拿着清单逐项打勾:"value 项写的是1哈,desc 项写的是视频哈,确认无误,签收!"

总结区别

场景 DELEGATING PROPERTIES
JSON 格式 单个值:1 完整对象:{"value":1, "desc":"视频"}
方法参数 一个参数 多个参数
适合 前端传数字/字符串表示枚举 前端传完整对象

四、和 @JsonValue 是"双向通道"

别忘了这个枚举里还有另一个注解:

java 复制代码
@JsonValue    // 序列化时告诉 Jackson 用这个字段
int value;

它俩的关系就像"一去一回":

复制代码
@JsonValue(枚举 → JSON)
SectionType.VIDEO  ────────────────→  数字 1

@JsonCreator(JSON → 枚举)
数字 1  ────────────────→  SectionType.VIDEO
  • @JsonValue :枚举转 JSON 时,输出 value(1 或 2),而不是枚举名字"VIDEO"
  • @JsonCreator :JSON 转枚举时,用 of() 方法把数字还原成对应枚举

两者配合,前端和数据库全程只跟数字打交道,完全不用关心枚举的 Java 类名是什么。


五、DELEGATING 底层原理简述

Jackson 在反序列化时的大致流程:

  1. 读取到 JSON 中的值(比如 1
  2. 检查目标类型 SectionType 是否有 @JsonCreator 注解
  3. 发现模式是 DELEGATING,直接把 1 作为参数调用 of(1)
  4. of() 方法遍历枚举值,找到 value=1 的枚举 → 返回 VIDEO

如果用 PROPERTIES,第 3 步就变成:先把 JSON 解析成 TokenBuffer,然后按参数名匹配绑定。


六、总结

注解/模式 方向 一句话
@JsonValue 枚举 → JSON 序列化时改用哪个字段输出
@JsonCreator JSON → 枚举 反序列化时调用哪个方法
DELEGATING 单值传入 适合前端只传一个数字/字符串
PROPERTIES 属性匹配 适合前端传完整对象需要拆开绑定

一句话核心@JsonCreator(mode = DELEGATING) 相当于给 Jackson 装了一个"数字 ↔ 枚举"的翻译器------前端传 1,Jackson 自动找 of(1) 翻译成 VIDEO,全程不需要你写繁琐的 if-else 转换代码。


如果你觉得这篇文章对你有帮助,欢迎点赞、收藏、转发!

有任何问题或建议,欢迎在评论区留言交流!

相关推荐
Flittly19 小时前
【AgentScope Java新手村系列】(14)人机交互
java·spring boot·spring
吃饱了得干活1 天前
Spring Cloud Gateway 微服务网关:路由、断言、过滤器
java·spring cloud
Flynt2 天前
从Spring Boot 4.0升到4.1,我在Maven和gRPC上栽了跟头
java·spring boot·后端
掉鱼的猫3 天前
Spring Boot → Solon 注解迁移实战指南:一张对照表说清楚
java·spring boot
人活一口气3 天前
Spring Boot与AIGC的完美结合:从零搭建智能内容生成平台
java·spring boot·aigc
唐青枫5 天前
Java Spring WebFlux 实战指南:用 Mono、Flux 和 WebClient 写响应式接口
java·spring
咖啡八杯6 天前
GoF设计模式——策略模式
java·后端·spring·设计模式
java小白小6 天前
SpringBoot(01): 初识SpringBoot,从Spring的痛点说起
spring boot
用户3169353811837 天前
如何从零编写一个 Spring Boot Starter
spring boot
程序员晓琪7 天前
约定大于配置:基于 Java 包名自动生成 API 版本路由的最佳实践
java·spring boot·后端