@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 转换代码。


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

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

相关推荐
李昊哲小课2 小时前
Spring Boot 4.0.6 全栈教程案例
spring boot·后端
亦暖筑序2 小时前
Java 8老系统旁路接入AI Gateway:不升级JDK也能用AI
java·spring boot·aigc·企业架构·ai gateway
摇滚侠3 小时前
Maven 的 <packaging>pom</packaging> 都有哪些值
java·maven
Mr.Entropy3 小时前
ecplise 导出maven依赖jar
java·maven·jar
摇滚侠3 小时前
Spring 零基础入门到进阶 入门 06-10
java·spring·intellij-idea
智碳未来科技有限公司3 小时前
工业双碳实践:基于 SpringBoot + 若依的智碳能源管理系统(zhitan-ems)源码深度解析与落地实战
spring boot·后端·能源
biubiubiu07063 小时前
SpringBoot生产级日志配置
java·spring boot·后端
碎碎念_4923 小时前
SpringBoot和MyBatis框架·速通版
spring boot·后端·mybatis
老码观察4 小时前
设计模式实战解读(十二):状态模式——干掉状态机里的 if-else 地狱
设计模式·状态模式