java枚举与json序列化框架配合需控制双向转换:jackson用@jsonvalue和@jsoncreator定制code字段,gson需typeadapter实现;策略上name语义清晰但兼容性弱,code更稳定,多字段建议对象格式,并注意反序列化安全兜底。

Java 枚举与 JSON 序列化框架配合使用时,核心在于控制序列化方向(枚举 → JSON)和反序列化方向(JSON → 枚举),不同框架默认行为不同,需根据实际需求显式配置。
Jackson:用 @JsonValue 和 @JsonCreator 精确控制
Jackson 默认将枚举序列化为名称(name()),反序列化也依赖名称匹配。若需转为自定义字段(如 code 或 description),推荐组合使用 @JsonValue 和 @JsonCreator:
-
@JsonValue 标在 getter 上,指定序列化输出值(例如返回
code字段) - @JsonCreator 标在静态工厂方法上,接收 JSON 值并构造对应枚举实例
- 注意:该工厂方法参数类型必须与
@JsonValue返回类型一致,且方法需声明为static
示例:
public enum Status {
SUCCESS(200, "操作成功"),
ERROR(500, "系统错误");
private final int code;
private final String desc;
Status(int code, String desc) {
this.code = code;
this.desc = desc;
}
@JsonValue
public int getCode() { return code; }
@JsonCreator
public static Status fromCode(int code) {
for (Status s : Status.values()) {
if (s.code == code) return s;
}
throw new IllegalArgumentException("Unknown code: " + code);
}
}
Gson:靠 TypeAdapter 实现双向定制
Gson 默认也序列化为 name,但不支持注解驱动的自动映射。要实现 code/desc 转换,需编写 TypeAdapter 并注册:
- 重写
write()方法,输出自定义字段(如out.value(status.getCode())) - 重写
read()方法,从 JSON 数值或字符串解析后匹配枚举实例 - 注册方式:构建
GsonBuilder时调用registerTypeAdapter(Status.class, new StatusAdapter())
优点是完全可控;缺点是每个枚举都要手动适配,适合统一规范场景。
序列化策略选择建议
是否暴露枚举内部结构,影响 API 兼容性和可读性:
- 用
name()(默认):语义清晰、调试友好,但名称变更即破坏兼容 - 用
code(整型/字符串常量):更稳定,适合状态码类枚举,但需确保 code 唯一且不重复 - 用
description或多字段对象:需序列化为 JSON 对象(如{"code":200,"desc":"成功"}),此时建议搭配@JsonFormat(shape = JsonFormat.Shape.OBJECT)(Jackson)或自定义 Adapter(Gson)
注意反序列化安全边界
无论用哪种框架,反序列化未知值都可能抛异常(如 IllegalArgumentException 或 JsonParseException)。生产环境建议:
- 在
@JsonCreator或TypeAdapter.read()中提供兜底逻辑(如返回 UNKNOWN 枚举项) - 避免直接抛 unchecked exception,可包装为业务异常或返回 Optional
- 对前端传入的枚举字段做校验层拦截(如 Spring 的
@Valid+ 自定义 ConstraintValidator)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











