Spring MVC中枚举序列化-如那边理VO中的枚举字段?

[复制链接]
发表于 3 天前 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
枚举是Java中表达有限状态的利器。使用枚举不仅可以增强类型安全,同时也会极大提升代码的可读性和可维护性。
在 Spring MVC 项目中,当使用 Jackson 序列化枚举类型时,默认举动是序列化枚举的 name() 值(即枚举常量的名称)。但在实际开发中,我们通常需要更灵活的控制。以下是详细分析息争决方案:
1. Jackson 默认枚举序列化举动
  1. public enum EnterpriseAuthStatusEnum {
  2.     PENDING,   // 序列化为 "PENDING"
  3.     APPROVED,  // 序列化为 "APPROVED"
  4.     REJECTED   // 序列化为 "REJECTED"
  5. }
复制代码
当 EnterpriseAuthStatusVO 对象被序列化为 JSON 时:
  1. {
  2.   "enterpriseId": 12345,
  3.   "kaiStatus": "PENDING"  // 默认输出枚举的 name() 值
  4. }
复制代码
2. 常见需求与解决方案

需求 1:返回枚举的说明笔墨(而非常量名)
  1. @JsonFormat(shape = JsonFormat.Shape.OBJECT) // 关键注解
  2. public enum EnterpriseAuthStatusEnum {
  3.     PENDING(0, "待审核"),
  4.     APPROVED(1, "已通过"),
  5.     REJECTED(2, "已拒绝");
  6.    
  7.     private final int code;
  8.     private final String description;
  9.    
  10.     EnterpriseAuthStatusEnum(int code, String description) {
  11.         this.code = code;
  12.         this.description = description;
  13.     }
  14.    
  15.     // 必须添加 getter
  16.     public int getCode() {
  17.         return code;
  18.     }
  19.    
  20.     public String getDescription() {
  21.         return description;
  22.     }
  23. }
复制代码
序列化结果:
  1. {
  2.   "enterpriseId": 12345,
  3.   "kaiStatus": {
  4.     "code": 0,
  5.     "description": "待审核"
  6.   }
  7. }
复制代码
需求 2:返回自定义值(如 code)
  1. public enum EnterpriseAuthStatusEnum {
  2.     PENDING(0),
  3.     APPROVED(1),
  4.     REJECTED(2);
  5.    
  6.     private final int code;
  7.    
  8.     EnterpriseAuthStatusEnum(int code) {
  9.         this.code = code;
  10.     }
  11.    
  12.     @JsonValue // 关键注解:标记作为序列化的值
  13.     public int getCode() {
  14.         return code;
  15.     }
  16. }
复制代码
序列化结果:
  1. {
  2.   "enterpriseId": 12345,
  3.   "kaiStatus": 0  // 直接输出 code 值
  4. }
复制代码
需求 3:根据不同场景返回不同值
  1. public enum EnterpriseAuthStatusEnum {
  2.     PENDING(0, "pending"),
  3.     APPROVED(1, "approved"),
  4.     REJECTED(2, "rejected");
  5.    
  6.     private final int code;
  7.     private final String text;
  8.    
  9.     EnterpriseAuthStatusEnum(int code, String text) {
  10.         this.code = code;
  11.         this.text = text;
  12.     }
  13.    
  14.     // 自定义序列化器
  15.     @JsonComponent
  16.     public static class Serializer extends StdSerializer<EnterpriseAuthStatusEnum> {
  17.         public Serializer() {
  18.             super(EnterpriseAuthStatusEnum.class);
  19.         }
  20.         
  21.         @Override
  22.         public void serialize(
  23.             EnterpriseAuthStatusEnum value,
  24.             JsonGenerator gen,
  25.             SerializerProvider provider
  26.         ) throws IOException {
  27.             // 根据业务需求选择输出字段
  28.             gen.writeString(value.text);
  29.             // 或 gen.writeNumber(value.code);
  30.         }
  31.     }
  32. }
复制代码
3. 全局配置方案(改变所有枚举举动)

在 application.yml 中配置:
  1. spring:
  2.   jackson:
  3.     serialization:
  4.       WRITE_ENUMS_USING_TO_STRING: true  # 使用 toString() 而非 name()
复制代码
或通过 Java 配置:
  1. @Configuration
  2. public class JacksonConfig {
  3.    
  4.     @Bean
  5.     public Jackson2ObjectMapperBuilderCustomizer enumCustomizer() {
  6.         return builder -> {
  7.             // 方案1: 使用 toString()
  8.             builder.featuresToEnable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING);
  9.             
  10.             // 方案2: 使用索引值
  11.             // builder.featuresToEnable(SerializationFeature.WRITE_ENUMS_USING_INDEX);
  12.         };
  13.     }
  14. }
复制代码
4. 最佳实践发起

方案一:返回带说明的完整对象(推荐)
  1. @Data
  2. public class EnumDTO {
  3.     private String name;
  4.     private int code;
  5.     private String description;
  6. }
  7. // 在VO中转换
  8. public class EnterpriseAuthStatusVO {
  9.     private Long enterpriseId;
  10.    
  11.     @JsonIgnore // 隐藏原始枚举
  12.     private EnterpriseAuthStatusEnum kaiStatus;
  13.    
  14.     @ApiModelProperty("客户开户状态")
  15.     public EnumDTO getKaiStatusInfo() {
  16.         if (kaiStatus == null) return null;
  17.         return new EnumDTO(
  18.             kaiStatus.name(),
  19.             kaiStatus.getCode(),
  20.             kaiStatus.getDescription()
  21.         );
  22.     }
  23. }
复制代码
序列化结果:
  1. {
  2.   "enterpriseId": 12345,
  3.   "kaiStatusInfo": {
  4.     "name": "PENDING",
  5.     "code": 0,
  6.     "description": "待审核"
  7.   }
  8. }
复制代码
方案二:使用统一响应包装器
  1. public class ApiResponse<T> {
  2.     private int code;
  3.     private String message;
  4.     private T data;
  5.    
  6.     // 成功响应时附加枚举元数据
  7.     public static <T> ApiResponse<T> success(T data, EnterpriseAuthStatusEnum status) {
  8.         ApiResponse<T> response = new ApiResponse<>();
  9.         response.code = 200;
  10.         response.message = status.getDescription();
  11.         response.data = data;
  12.         return response;
  13.     }
  14. }
复制代码
5. 完整示例代码
  1. // 枚举定义
  2. @JsonFormat(shape = JsonFormat.Shape.OBJECT)
  3. public enum EnterpriseAuthStatusEnum {
  4.     PENDING(0, "待审核"),
  5.     APPROVED(1, "已通过"),
  6.     REJECTED(2, "已拒绝");
  7.    
  8.     private final int code;
  9.     private final String description;
  10.    
  11.     // 构造方法、getter
  12. }
  13. // VO对象
  14. @Data
  15. @EqualsAndHashCode(callSuper = false)
  16. @Accessors(chain = true)
  17. public class EnterpriseAuthStatusVO implements Serializable {
  18.     private static final long serialVersionUID = 1L;
  19.    
  20.     @ApiModelProperty("企业id")
  21.     private Long enterpriseId;
  22.    
  23.     @ApiModelProperty("客户开户状态")
  24.     private EnterpriseAuthStatusEnum kaiStatus;
  25. }
  26. // 控制器
  27. @RestController
  28. public class EnterpriseController {
  29.    
  30.     @GetMapping("/auth/status")
  31.     public EnterpriseAuthStatusVO getAuthStatus() {
  32.         return new EnterpriseAuthStatusVO()
  33.             .setEnterpriseId(10001L)
  34.             .setKaiStatus(EnterpriseAuthStatusEnum.PENDING);
  35.     }
  36. }
复制代码
请求响应:
  1. {
  2.   "enterpriseId": 10001,
  3.   "kaiStatus": {
  4.     "code": 0,
  5.     "description": "待审核"
  6.   }
  7. }
复制代码
关键总结

需求场景实现方案序列化结果示例默认举动无配置"ENDING"返回数字编码@JsonValue + getCode()0返回完整对象@JsonFormat(shape = OBJECT){"code":0, "desc":"待审核"}全局使用 toString()WRITE_ENUMS_USING_TO_STRING"待审核"自定义序列化逻辑实现 JsonSerializer任意自定义格式生产情况推荐:使用 @JsonFormat(shape = OBJECT) 返回完整枚举信息,前端可直接展示 description 字段,同时保存 code 用于逻辑判断。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

© 2001-2025 Discuz! Team. Powered by Discuz! X3.5

GMT+8, 2025-6-19 18:15 , Processed in 0.056891 second(s), 24 queries 手机版|qidao123.com技术社区-IT企服评测▪应用市场 ( 浙ICP备20004199 )

快速回复 返回顶部 返回列表