@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 在反序列化时的大致流程:
- 读取到 JSON 中的值(比如
1) - 检查目标类型
SectionType是否有@JsonCreator注解 - 发现模式是
DELEGATING,直接把1作为参数调用of(1) 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 转换代码。
如果你觉得这篇文章对你有帮助,欢迎点赞、收藏、转发!
有任何问题或建议,欢迎在评论区留言交流!