在使用Jackson進行JSON序列化時,有時我們需要在序列化枚舉類型時,不僅輸出枚舉值,還需要輸出其對應(yīng)的文本描述。本文將介紹如何通過自定義序列化器來實現(xiàn)這個功能。
1. 定義枚舉接口
首先,我們定義一個通用的枚舉接口,用于規(guī)范枚舉類型:
public interface ValueEnum {
String getCode();
String getText();
}
2. 實現(xiàn)示例枚舉
創(chuàng)建一個示例枚舉類實現(xiàn)上述接口:
public enum StatusEnum implements ValueEnum {
ACTIVE("1", "激活"),
INACTIVE("0", "未激活");
private final String code;
private final String text;
StatusEnum(String code, String text) {
this.code = code;
this.text = text;
}
@Override
public String getCode() {
return code;
}
@Override
public String getText() {
return text;
}
}
3. 自定義序列化器
實現(xiàn)自定義序列化器,用于在序列化時同時輸出枚舉值和文本描述:
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import java.io.IOException;
import java.util.Objects;
/**
* 自定義枚舉序列化器,用于在序列化時添加文本字段
* @JsonSerialize(using = AddFieldJsonSerializer.class, nullsUsing = AddFieldJsonSerializer.class)
*/
public class AddFieldJsonSerializer extends JsonSerializer<ValueEnum> {
@Override
public void serialize(ValueEnum valueEnum, JsonGenerator gen, SerializerProvider serializerProvider) throws IOException {
// 獲取當(dāng)前字段名稱
String fieldName = gen.getOutputContext().getCurrentName();
if (Objects.nonNull(valueEnum)) {
// 寫入原始字段的值
gen.writeString(String.valueOf(valueEnum.getCode()));
} else {
gen.writeNull();
}
// 寫入新增的文本字段
gen.writeFieldName(fieldName.concat("Text"));
if (Objects.nonNull(valueEnum)) {
gen.writeString(valueEnum.getText());
} else {
gen.writeNull();
}
}
}
4. 創(chuàng)建測試實體類
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
public class User {
private String id;
@JsonSerialize(using = AddFieldJsonSerializer.class, nullsUsing = AddFieldJsonSerializer.class)
private StatusEnum status;
// getter和setter方法
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public StatusEnum getStatus() {
return status;
}
public void setStatus(StatusEnum status) {
this.status = status;
}
}
- 編寫測試用例
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class AddFieldJsonSerializerTest {
@Test
public void testSerializeEnum() throws Exception {
// 準備測試數(shù)據(jù)
User user = new User();
user.setId("1");
user.setStatus(StatusEnum.ACTIVE);
// 序列化
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(user);
// 驗證結(jié)果
String expectedJson = "{\"id\":\"1\",\"status\":\"1\",\"statusText\":\"激活\"}";
assertEquals(expectedJson, json);
// 測試空值情況
user.setStatus(null);
json = mapper.writeValueAsString(user);
expectedJson = "{\"id\":\"1\",\"status\":null,\"statusText\":null}";
assertEquals(expectedJson, json);
}
}
6. 添加Maven依賴
<dependencies>
<!-- Jackson依賴 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.15.2</version>
</dependency>
<!-- 測試依賴 -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.9.2</version>
<scope>test</scope>
</dependency>
</dependencies>
序列化結(jié)果說明
當(dāng)我們使用這個自定義序列化器后,JSON輸出將包含兩個字段:
- 原始字段:包含枚舉的code值
- 文本字段:字段名為原始字段名+"Text"后綴,包含枚舉的文本描述
例如,對于上面的測試用例,輸出結(jié)果為:
{
"id": "1",
"status": "1",
"statusText": "激活"
}