Spring MVC中枚举序列化-如何处理VO中的枚举字段?
枚举是Java中表达有限状态的利器。使用枚举不仅可以增强类型安全,同时也会极大提升代码的可读性和可维护性。在 Spring MVC 项目中,当使用 Jackson 序列化枚举类型时,默认行为是序列化枚举的 name() 值(即枚举常量的名称)。但在实际开发中,我们通常需要更灵活的控制。以下是详细分析和解决方案:
1. Jackson 默认枚举序列化行为
public enum EnterpriseAuthStatusEnum {
PENDING, // 序列化为 "PENDING"
APPROVED,// 序列化为 "APPROVED"
REJECTED // 序列化为 "REJECTED"
}当 EnterpriseAuthStatusVO 对象被序列化为 JSON 时:
{
"enterpriseId": 12345,
"kaiStatus": "PENDING"// 默认输出枚举的 name() 值
}2. 常见需求与解决方案
需求 1:返回枚举的说明文字(而非常量名)
@JsonFormat(shape = JsonFormat.Shape.OBJECT) // 关键注解
public enum EnterpriseAuthStatusEnum {
PENDING(0, "待审核"),
APPROVED(1, "已通过"),
REJECTED(2, "已拒绝");
private final int code;
private final String description;
EnterpriseAuthStatusEnum(int code, String description) {
this.code = code;
this.description = description;
}
// 必须添加 getter
public int getCode() {
return code;
}
public String getDescription() {
return description;
}
}序列化结果:
{
"enterpriseId": 12345,
"kaiStatus": {
"code": 0,
"description": "待审核"
}
}需求 2:返回自定义值(如 code)
public enum EnterpriseAuthStatusEnum {
PENDING(0),
APPROVED(1),
REJECTED(2);
private final int code;
EnterpriseAuthStatusEnum(int code) {
this.code = code;
}
@JsonValue // 关键注解:标记作为序列化的值
public int getCode() {
return code;
}
}序列化结果:
{
"enterpriseId": 12345,
"kaiStatus": 0// 直接输出 code 值
}需求 3:根据不同场景返回不同值
public enum EnterpriseAuthStatusEnum {
PENDING(0, "pending"),
APPROVED(1, "approved"),
REJECTED(2, "rejected");
private final int code;
private final String text;
EnterpriseAuthStatusEnum(int code, String text) {
this.code = code;
this.text = text;
}
// 自定义序列化器
@JsonComponent
public static class Serializer extends StdSerializer<EnterpriseAuthStatusEnum> {
public Serializer() {
super(EnterpriseAuthStatusEnum.class);
}
@Override
public void serialize(
EnterpriseAuthStatusEnum value,
JsonGenerator gen,
SerializerProvider provider
) throws IOException {
// 根据业务需求选择输出字段
gen.writeString(value.text);
// 或 gen.writeNumber(value.code);
}
}
}3. 全局配置方案(改变所有枚举行为)
在 application.yml 中配置:
spring:
jackson:
serialization:
WRITE_ENUMS_USING_TO_STRING: true# 使用 toString() 而非 name()或通过 Java 配置:
@Configuration
public class JacksonConfig {
@Bean
public Jackson2ObjectMapperBuilderCustomizer enumCustomizer() {
return builder -> {
// 方案1: 使用 toString()
builder.featuresToEnable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING);
// 方案2: 使用索引值
// builder.featuresToEnable(SerializationFeature.WRITE_ENUMS_USING_INDEX);
};
}
}4. 最佳实践建议
方案一:返回带说明的完整对象(推荐)
@Data
public class EnumDTO {
private String name;
private int code;
private String description;
}
// 在VO中转换
public class EnterpriseAuthStatusVO {
private Long enterpriseId;
@JsonIgnore // 隐藏原始枚举
private EnterpriseAuthStatusEnum kaiStatus;
@ApiModelProperty("客户开户状态")
public EnumDTO getKaiStatusInfo() {
if (kaiStatus == null) return null;
return new EnumDTO(
kaiStatus.name(),
kaiStatus.getCode(),
kaiStatus.getDescription()
);
}
}序列化结果:
{
"enterpriseId": 12345,
"kaiStatusInfo": {
"name": "PENDING",
"code": 0,
"description": "待审核"
}
}方案二:使用统一响应包装器
public class ApiResponse<T> {
private int code;
private String message;
private T data;
// 成功响应时附加枚举元数据
public static <T> ApiResponse<T> success(T data, EnterpriseAuthStatusEnum status) {
ApiResponse<T> response = new ApiResponse<>();
response.code = 200;
response.message = status.getDescription();
response.data = data;
return response;
}
}5. 完整示例代码
// 枚举定义
@JsonFormat(shape = JsonFormat.Shape.OBJECT)
public enum EnterpriseAuthStatusEnum {
PENDING(0, "待审核"),
APPROVED(1, "已通过"),
REJECTED(2, "已拒绝");
private final int code;
private final String description;
// 构造方法、getter
}
// VO对象
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
public class EnterpriseAuthStatusVO implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty("企业id")
private Long enterpriseId;
@ApiModelProperty("客户开户状态")
private EnterpriseAuthStatusEnum kaiStatus;
}
// 控制器
@RestController
public class EnterpriseController {
@GetMapping("/auth/status")
public EnterpriseAuthStatusVO getAuthStatus() {
return new EnterpriseAuthStatusVO()
.setEnterpriseId(10001L)
.setKaiStatus(EnterpriseAuthStatusEnum.PENDING);
}
}请求响应:
{
"enterpriseId": 10001,
"kaiStatus": {
"code": 0,
"description": "待审核"
}
}关键总结
需求场景实现方案序列化结果示例默认行为无配置"PENDING"返回数字编码@JsonValue + getCode()0返回完整对象@JsonFormat(shape = OBJECT){"code":0, "desc":"待审核"}全局使用 toString()WRITE_ENUMS_USING_TO_STRING"待审核"自定义序列化逻辑实现 JsonSerializer任意自定义格式生产环境推荐:使用 @JsonFormat(shape = OBJECT) 返回完整枚举信息,前端可直接展示 description 字段,同时保留 code 用于逻辑判断。
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页:
[1]