我在 mongodb 中以传统方式(kebab-case)存储了很多枚举。但所有枚举都以 SCREAMING_SNAKE_CASE 形式存储在 Java 代码中。我创建了一个新的微服务,它使用 spring-data-mongodb ,它将使用以这种方式存储枚举的所有集合。我不能破坏向后兼容性,所以我必须以 kebab-case 方式读取和写入它们。是否可以为枚举创建一个通用转换器(例如,用
@KebabCaseStore
注释),以正确的方式保存此类,而无需为每个枚举编写自定义读/写转换器?
好吧,我终于做到了。
@ReadingConverter
class StringToEnumReaderConverterFactory(
enums: Collection<Class<out Enum<*>>>
) : ConditionalGenericConverter {
private val enumClassToItsConstants: Map<Class<out Enum<*>>, Map<String, Enum<*>>> =
enums.associateWith { it.enumConstants.associateBy { enumConstant -> enumConstant.name } }
override fun getConvertibleTypes(): MutableSet<GenericConverter.ConvertiblePair> {
return enumClassToItsConstants.keys.map { enumClass ->
GenericConverter.ConvertiblePair(
String::class.java,
enumClass
)
}
.toMutableSet()
}
override fun convert(source: Any?, sourceType: TypeDescriptor, targetType: TypeDescriptor): Any? {
val s: String = source?.let { it as String }
?.uppercase()
?.replace("-", "_")
?: return null
val constants = enumClassToItsConstants[targetType.objectType]
return constants?.get(s)
}
override fun matches(sourceType: TypeDescriptor, targetType: TypeDescriptor): Boolean {
return enumClassToItsConstants.containsKey(targetType.objectType)
}
}
@WritingConverter
class EnumToStringWritingConverterFactory(
enums: Collection<Class<out Enum<*>>>
) : ConditionalGenericConverter {
private val enums = enums.toSet()
override fun getConvertibleTypes(): MutableSet<GenericConverter.ConvertiblePair> {
return enums.map { GenericConverter.ConvertiblePair(it, String::class.java) }.toMutableSet()
}
override fun convert(source: Any?, sourceType: TypeDescriptor, targetType: TypeDescriptor): Any {
val enum = source as Enum<*>
return enum.name.lowercase().replace("_", "-")
}
override fun matches(sourceType: TypeDescriptor, targetType: TypeDescriptor): Boolean {
return sourceType.objectType in enums
}
}