You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Spring匹配大小写不一致的枚举类型?

问题描述

原本定义的Kotlin枚举:

enum class CallbackStatus{ success, failed }

因ktlint提示枚举名称小写不符合规范,修改为:

enum class CallbackStatus{ SUCCESS, FAILED }

修改后多个测试失败,报错信息:

Failed to convert from type [java.lang.String] to type [@org.springframework.web.bind.annotation.PathVariable no.posten.push.notification.CallbackStatus] for value 'failed'; nested exception is java.lang.IllegalArgumentException: No enum constant mypackage.CallbackStatus.failed

该枚举用于Spring接口的路径变量:

@PostMapping("{status}")
fun handleCallback(
  @PathVariable callbackReference: String,
  @PathVariable status: CallbackStatus,
  @RequestBody callback: Callback,
  @RequestHeader(notificationEngineCallbackHeader) callbackSecret: String,
): ResponseEntity<Any> =

需求:让Spring自动将字符串"failed"转换为CallbackStatus.FAILED,疑问:是否需要重写StringToEnumConverterFactory?


解决方案

不需要重写StringToEnumConverterFactory,以下几种简便方式即可解决:

1. 自定义枚举转换方法 + 注册Converter

在枚举类中添加静态方法处理字符串匹配,再注册自定义Converter到Spring:

enum class CallbackStatus {
    SUCCESS, FAILED;

    companion object {
        fun fromString(value: String): CallbackStatus {
            return values().firstOrNull { it.name.equals(value, ignoreCase = true) }
                ?: throw IllegalArgumentException("Invalid status: $value")
        }
    }
}

创建自定义Converter:

@Component
class StringToCallbackStatusConverter : Converter<String, CallbackStatus> {
    override fun convert(source: String): CallbackStatus {
        return CallbackStatus.fromString(source)
    }
}

Spring会自动识别并使用该Converter替代默认枚举转换逻辑。

2. 使用@JsonCreator注解(推荐)

在枚举的静态转换方法上添加@JsonCreator,同时配合@JvmStatic让Spring能识别该方法,既支持JSON序列化,也能处理路径变量的转换:

enum class CallbackStatus {
    SUCCESS, FAILED;

    companion object {
        @JsonCreator
        @JvmStatic
        fun fromString(value: String): CallbackStatus {
            return values().firstOrNull { it.name.equals(value, ignoreCase = true) }
                ?: throw IllegalArgumentException("Invalid status: $value")
        }
    }
}

这种方式无需额外注册组件,代码侵入性低,实现简洁。

3. 全局配置枚举忽略大小写转换

如果希望所有枚举都支持忽略大小写的字符串转换,可以通过配置ConversionService实现:

@Configuration
class WebConfig : WebMvcConfigurer {
    override fun addFormatters(registry: FormatterRegistry) {
        registry.addConverter(String::class.java, Enum::class.java) { source, targetType ->
            @Suppress("UNCHECKED_CAST")
            val enumType = targetType as Class<Enum<*>>
            Enum.valueOf(enumType, source.uppercase())
        }
    }
}

该配置会对所有枚举生效,自动将输入字符串转为大写后匹配枚举常量。


总结

优先选择第二种@JsonCreator的方式,简洁且适配场景广;若仅需单独处理某个枚举,用第一种自定义Converter;全局所有枚举都需要忽略大小写时,用第三种配置方案。无需重写StringToEnumConverterFactory,上述方式更灵活易维护。

内容的提问来源于stack exchange,提问作者oligofren

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 02:16:11