重写 toString() 对 JSON 序列化无效,因为 Jackson 和 FastJSON 默认使用 name() 而非 toString() 输出枚举字符串;推荐用 @JsonValue 注解 getter 方法返回友好文本,或用 @JsonFormat(shape = OBJECT) 输出 code + label 结构化数据。

Java 枚举默认的 toString() 返回的是枚举常量名(如 USER),而前端通常需要更友好的中文描述(如 "用户")或结构化字段。直接重写 toString() 并不能可靠控制 JSON 序列化结果,因为主流 JSON 库(如 Jackson、FastJSON)默认序列化枚举时,用的是 name() 或自定义序列化器,toString() 不会被自动调用。
为什么重写 toString() 对 JSON 序列化无效?
Jackson 默认将枚举序列化为字符串时,输出的是 name()(即大写常量名),不是 toString() 的返回值。FastJSON 行为类似。除非显式配置序列化器,否则 toString() 只在日志、打印、调试等场景生效,不参与 JSON 输出。
推荐做法:用 @JsonValue + 自定义字段
让枚举携带可读文本,并通过 @JsonValue 告诉 Jackson 使用哪个方法作为序列化值:
- 定义一个私有字段(如
desc)存储前端需要的展示文本 - 提供 getter 方法(如
getDesc()) - 在该 getter 上加
@JsonValue注解
示例:
立即学习“Java免费学习笔记(深入)”;
public enum UserType {
ADMIN("管理员"),
USER("普通用户"),
GUEST("访客");
private final String desc;
UserType(String desc) {
this.desc = desc;
}
@JsonValue
public String getDesc() {
return desc;
}
}
这样序列化后 JSON 就是 "管理员"、"普通用户" 等字符串,前端可直接使用。
补充:前端需要 code + label 时,用 @JsonFormat 或自定义序列化器
如果前端需要同时拿到枚举的英文 code(如 "ADMIN")和中文 label(如 "管理员"),建议返回对象而非字符串:
- 不重写
toString(),也不用@JsonValue - 定义一个 DTO 或直接在枚举中提供
toMap()/toJson()方法 - 或配合
@JsonFormat(shape = JsonFormat.Shape.OBJECT)(Jackson 2.12+)
例如:
@JsonFormat(shape = JsonFormat.Shape.OBJECT)
public enum Status {
ACTIVE("ACTIVE", "启用"),
INACTIVE("INACTIVE", "停用");
private final String code;
private final String label;
Status(String code, String label) {
this.code = code;
this.label = label;
}
public String getCode() { return code; }
public String getLabel() { return label; }
}
序列化结果为:{"code":"ACTIVE","label":"启用"},前后端契约清晰。
不推荐:仅靠重写 toString() 配合 JSON 库
虽然可以强行让 Jackson 使用 toString()(如注册自定义 SimpleModule + ToStringSerializer),但这样做:
- 全局影响所有枚举,容易误伤
- 丧失 code 字段,无法做后端逻辑判断(比如
if (type == ADMIN)) - 与前端约定脱节,不可扩展
维护成本高,且违背枚举的设计初衷——类型安全 + 明确语义。


















