別再用 toString() 了!Spring Boot + Jackson 處理枚舉的七種方式
環境:SpringBoot3.4.2
1. 簡介
在系統開發中,JSON 作為輕量級數據交換格式被廣泛應用,而枚舉(Enum)作為 Java 等語言中表示固定常量集合的類型,其與 JSON 的交互處理至關重要。傳統場景下,枚舉序列化可能直接輸出其名稱(如 "MALE"),但實際業務中常需更靈活的映射,例如輸出數字代碼(1)或國際化描述("男")。同時,反序列化時需根據 JSON 值(如數字或字符串)精準匹配枚舉實例。
本篇文章將詳細介紹枚舉值在序列化和反序列化過程中的核心處理機制、常見應用場景及最佳實踐方案。
2.實戰案例
2.1 準備環境
定義性別枚舉類
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實體對象包括上面的枚舉字段
public record User(String name, int age, Gender gender) {
}2.2 默認輸出枚舉值
@RestController
@RequestMapping("/users")
public class UserController {
@GetMapping
public ResponseEntity<User> query() {
return ResponseEntity.ok(new User("Pack_xg", 33, Gender.MALE)) ;
}
}輸出結果

2.3 將枚舉序列化為JSON對象
當我們希望將枚舉值序列化為如下格式:
{"code": 1, "name": "男"}要輸出此格式,我們可以通過如下注解進行標注枚舉類:
@JsonFormat(shape = JsonFormat.Shape.OBJECT)
public enum Gender {
// ...
}輸出結果
圖片
2.4 枚舉與@JsonValue結合
控制枚舉序列化輸出的另一種簡單方法是在 getter 方法上使用 @JsonValue 注解。該注解用于指示被注解的訪問器(字段或“getter”方法[非void返回類型、無參數的方法])的值應作為該實例的單一值進行序列化,而非采用常規的收集屬性值的方式。
修改枚舉類如下:
public enum Gender {
// ...
@JsonValue
public String getName() {
return name;
}
}在我們希望輸出的字段上使用@JsonValue注解。
輸出結果
圖片
當我們將@JsonValue使用到類中的toString時,如下:
public record User(String name, int age, Gender gender) {
@JsonValue
public String toString() {
return "【name = " + this.name + ", age = " + this.age + ", gender = " + this.gender + "】";
}
}輸出結果
圖片
2.5 自定義枚舉序列化
我們可以通過繼承 StdSerializer 的方式,實現自定義的序列化方式,如下示例:
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 {}輸出結果
圖片
2.6 反序列化枚舉
@PostMapping
public ResponseEntity<User> save(@RequestBody User user) {
return ResponseEntity.ok(user) ;
}默認情況
圖片
我們修改gender值為數字也同樣可以,如下:
圖片
使用@JsonValue
public enum Gender {
@JsonValue
public int getCode() {
return code;
}
}輸出結果
圖片
這時候你再換成枚舉的字面量值將會報錯,如下:
圖片
使用@JsonProperty
通過使用此注解,我們只是告訴Jackson將@JsonProperty的值映射到標注此值的對象。如下示例:
修改枚舉類
public enum Gender {
@JsonProperty("unknow")
UNKNOWN(0, "未知的性別"),
@JsonProperty("male")
MALE(1, "男"),
@JsonProperty("female")
FEMALE(2, "女"),
@JsonProperty("unknow_gender")
UNSTATED(9, "未說明的性別");
}輸出結果
圖片
圖片
使用@JsonCreator
該注解用于將構造函數或工廠方法定義為用于實例化關聯類新實例的指定方法。
修改枚舉類如下:
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);
}
}輸出結果
圖片
自定義反序列化
定義反序列化類
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 {}輸出結果
圖片



































