Java中MongoDB带@KebabCaseStore注解的通用枚举转换器实现咨询
实现带@KebabCaseStore注解的通用MongoDB枚举转换器
问题背景
MongoDB中以kebab-case格式存储了大量枚举值,但Java代码里所有枚举都用SCREAMING_SNAKE_CASE格式。基于Spring Data MongoDB开发新微服务时,需要保证读写枚举时自动在两种格式间转换,且不用为每个枚举单独写自定义转换器。
解决方案
可以通过自定义注解+Spring Data MongoDB的GenericConverter实现通用枚举转换逻辑,仅对标记了注解的枚举生效,兼顾兼容性与通用性。
1. 定义@KebabCaseStore注解
创建用于标记需要进行格式转换的枚举类:
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface KebabCaseStore { }
2. 实现通用读转换器(MongoDB → Java)
将MongoDB中的kebab-case字符串转换为Java枚举的SCREAMING_SNAKE_CASE格式:
@Component public class KebabCaseToEnumConverter implements GenericConverter { @Override public Set<ConvertiblePair> getConvertibleTypes() { return Collections.singleton(new ConvertiblePair(String.class, Enum.class)); } @Override public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) { if (source == null) { return null; } Class<?> enumType = targetType.getType(); // 仅处理标记了@KebabCaseStore的枚举 if (!enumType.isAnnotationPresent(KebabCaseStore.class)) { return Enum.valueOf((Class<? extends Enum<?>>) enumType, (String) source); } // kebab-case转SCREAMING_SNAKE_CASE:替换连字符为下划线并转大写 String enumName = ((String) source).replace("-", "_").toUpperCase(); return Enum.valueOf((Class<? extends Enum<?>>) enumType, enumName); } }
3. 实现通用写转换器(Java → MongoDB)
将Java枚举的SCREAMING_SNAKE_CASE格式转换为MongoDB存储的kebab-case字符串:
@Component public class EnumToKebabCaseConverter implements GenericConverter { @Override public Set<ConvertiblePair> getConvertibleTypes() { return Collections.singleton(new ConvertiblePair(Enum.class, String.class)); } @Override public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) { if (source == null) { return null; } Enum<?> enumValue = (Enum<?>) source; Class<?> enumType = sourceType.getType(); // 仅处理标记了@KebabCaseStore的枚举 if (!enumType.isAnnotationPresent(KebabCaseStore.class)) { return enumValue.name(); } // SCREAMING_SNAKE_CASE转kebab-case:转小写并替换下划线为连字符 return enumValue.name().toLowerCase().replace("_", "-"); } }
4. 注册转换器到Spring上下文
通过配置类将自定义转换器注册到MongoDB的转换体系中:
@Configuration public class MongoConfig { private final KebabCaseToEnumConverter kebabCaseToEnumConverter; private final EnumToKebabCaseConverter enumToKebabCaseConverter; // 构造注入转换器 public MongoConfig(KebabCaseToEnumConverter kebabCaseToEnumConverter, EnumToKebabCaseConverter enumToKebabCaseConverter) { this.kebabCaseToEnumConverter = kebabCaseToEnumConverter; this.enumToKebabCaseConverter = enumToKebabCaseConverter; } @Bean public MongoCustomConversions customConversions() { return new MongoCustomConversions(Arrays.asList( kebabCaseToEnumConverter, enumToKebabCaseConverter )); } }
5. 使用示例
给需要进行格式转换的枚举类添加@KebabCaseStore注解即可:
@KebabCaseStore public enum OrderStatus { CREATED, PROCESSING, SHIPPED, DELIVERED }
此时:
- 从MongoDB读取
"created"会自动转为OrderStatus.CREATED - 写入MongoDB时,
OrderStatus.PROCESSING会自动转为"processing"
注意事项
- 确保枚举的格式映射是严格的:SCREAMING_SNAKE_CASE与kebab-case仅通过大小写和下划线/连字符替换对应,无特殊命名规则差异
- 若部分枚举需要特殊转换逻辑,可单独编写对应转换器,Spring会优先使用更具体的类型转换器
- 未标记
@KebabCaseStore的枚举仍会使用Spring Data MongoDB的默认枚举转换逻辑
内容的提问来源于stack exchange,提问作者Fagam32
相关产品推荐
相关产品推荐

