別再用 toString() 了!Spring Boot + Jackson 處理枚舉的七種方式
環(huán)境:SpringBoot3.4.2
1. 簡介
在系統(tǒng)開發(fā)中,JSON 作為輕量級(jí)數(shù)據(jù)交換格式被廣泛應(yīng)用,而枚舉(Enum)作為 Java 等語言中表示固定常量集合的類型,其與 JSON 的交互處理至關(guān)重要。傳統(tǒng)場(chǎng)景下,枚舉序列化可能直接輸出其名稱(如 "MALE"),但實(shí)際業(yè)務(wù)中常需更靈活的映射,例如輸出數(shù)字代碼(1)或國際化描述("男")。同時(shí),反序列化時(shí)需根據(jù) JSON 值(如數(shù)字或字符串)精準(zhǔn)匹配枚舉實(shí)例。
本篇文章將詳細(xì)介紹枚舉值在序列化和反序列化過程中的核心處理機(jī)制、常見應(yīng)用場(chǎng)景及最佳實(shí)踐方案。
2.實(shí)戰(zhàn)案例
2.1 準(zhǔn)備環(huán)境
定義性別枚舉類
public enum Gender {
UNKNOWN(0, "未知的性別"), MALE(1, "男"), FEMALE(2, "女"), UNSTATED(9, "未說明的性別");
private final int code;
private final String name;
Gender(int code, String name) {
this.code = code;
this.name = name;
}
public int getCode() {
return code ;
}
public String getName() {
return name ;
}
}定義User實(shí)體對(duì)象包括上面的枚舉字段
public record User(String name, int age, Gender gender) {
}2.2 默認(rèn)輸出枚舉值
@RestController
@RequestMapping("/users")
public class UserController {
@GetMapping
public ResponseEntity<User> query() {
return ResponseEntity.ok(new User("Pack_xg", 33, Gender.MALE)) ;
}
}輸出結(jié)果

2.3 將枚舉序列化為JSON對(duì)象
當(dāng)我們希望將枚舉值序列化為如下格式:
{"code": 1, "name": "男"}要輸出此格式,我們可以通過如下注解進(jìn)行標(biāo)注枚舉類:
@JsonFormat(shape = JsonFormat.Shape.OBJECT)
public enum Gender {
// ...
}輸出結(jié)果
圖片
2.4 枚舉與@JsonValue結(jié)合
控制枚舉序列化輸出的另一種簡單方法是在 getter 方法上使用 @JsonValue 注解。該注解用于指示被注解的訪問器(字段或“getter”方法[非void返回類型、無參數(shù)的方法])的值應(yīng)作為該實(shí)例的單一值進(jìn)行序列化,而非采用常規(guī)的收集屬性值的方式。
修改枚舉類如下:
public enum Gender {
// ...
@JsonValue
public String getName() {
return name;
}
}在我們希望輸出的字段上使用@JsonValue注解。
輸出結(jié)果
圖片
當(dāng)我們將@JsonValue使用到類中的toString時(shí),如下:
public record User(String name, int age, Gender gender) {
@JsonValue
public String toString() {
return "【name = " + this.name + ", age = " + this.age + ", gender = " + this.gender + "】";
}
}輸出結(jié)果
圖片
2.5 自定義枚舉序列化
我們可以通過繼承 StdSerializer 的方式,實(shí)現(xiàn)自定義的序列化方式,如下示例:
public class GenderSerializer extends StdSerializer<Gender> {
public GenderSerializer() {
super(Gender.class);
}
public GenderSerializer(Class<Gender> t) {
super(t);
}
public void serialize(Gender value, JsonGenerator generator, SerializerProvider provider)
throws IOException, JsonProcessingException {
generator.writeStartObject() ;
generator.writeFieldName("label") ;
generator.writeString(value.name()) ;
generator.writeFieldName("value") ;
generator.writeNumber(value.getCode()) ;
generator.writeEndObject();
}
}接著修改Gender枚舉類
@JsonSerialize(using = GenderSerializer.class)
public enum Gender {}輸出結(jié)果
圖片
2.6 反序列化枚舉
@PostMapping
public ResponseEntity<User> save(@RequestBody User user) {
return ResponseEntity.ok(user) ;
}默認(rèn)情況
圖片
我們修改gender值為數(shù)字也同樣可以,如下:
圖片
使用@JsonValue
public enum Gender {
@JsonValue
public int getCode() {
return code;
}
}輸出結(jié)果
圖片
這時(shí)候你再換成枚舉的字面量值將會(huì)報(bào)錯(cuò),如下:
圖片
使用@JsonProperty
通過使用此注解,我們只是告訴Jackson將@JsonProperty的值映射到標(biāo)注此值的對(duì)象。如下示例:
修改枚舉類
public enum Gender {
@JsonProperty("unknow")
UNKNOWN(0, "未知的性別"),
@JsonProperty("male")
MALE(1, "男"),
@JsonProperty("female")
FEMALE(2, "女"),
@JsonProperty("unknow_gender")
UNSTATED(9, "未說明的性別");
}輸出結(jié)果
圖片
圖片
使用@JsonCreator
該注解用于將構(gòu)造函數(shù)或工廠方法定義為用于實(shí)例化關(guān)聯(lián)類新實(shí)例的指定方法。
修改枚舉類如下:
public enum Gender {
// ...
@JsonCreator
public Gender fromCode(@JsonProperty("gender") int code) {
for (Gender gender : Gender.values()) {
if (gender.code == code) {
return gender;
}
}
throw new IllegalArgumentException("無效的性別代碼: " + code);
}
}輸出結(jié)果
圖片
自定義反序列化
定義反序列化類
public class GenderDeserializer extends StdDeserializer<Gender> {
public GenderDeserializer() {
super(Gender.class) ;
}
@Override
public Gender deserialize(JsonParser jsonParser, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
int gender = jsonParser.getValueAsInt() ;
for (Gender g : Gender.values()) {
if (g.getCode() == gender) {
return g ;
}
}
return null;
}
}修改枚舉類
@JsonDeserialize(using = GenderDeserializer.class)
public enum Gender {}輸出結(jié)果
圖片


































