java 中 mongodb 的自定义通用枚举转换器

问题描述 投票:0回答:1

我在 mongodb 中以传统方式(kebab-case)存储了很多枚举。但所有枚举都以 SCREAMING_SNAKE_CASE 形式存储在 Java 代码中。我创建了一个新的微服务,它使用 spring-data-mongodb ,它将使用以这种方式存储枚举的所有集合。我不能破坏向后兼容性,所以我必须以 kebab-case 方式读取和写入它们。是否可以为枚举创建一个通用转换器(例如,用

@KebabCaseStore
注释),以正确的方式保存此类,而无需为每个枚举编写自定义读/写转换器?

java spring-data spring-data-mongodb
1个回答
0
投票

好吧,我终于做到了。

@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
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.