Kotlin中@QueryValue注解下如何反序列化枚举为指定小写值?
解决Query参数传递枚举时@JsonProperty不生效的问题
问题原因
通过Query参数传递对象时,枚举的序列化/反序列化由Spring的ConversionService处理,而非Jackson(仅@Body注解的参数会用Jackson解析)。因此@JsonProperty注解和Jackson的ACCEPT_CASE_INSENSITIVE_ENUMS配置对Query参数完全不起作用,默认会使用枚举的name()值(即大写形式)。
解决方案
方案1:重写枚举的toString()方法(简单直接)
如果枚举的目标值可以直接在枚举中定义,重写toString()让Query参数序列化时使用该值,同时不影响@Body的Jackson解析逻辑:
enum class StudentName(val value: String) { @JsonProperty("ram") RAM("ram"), @JsonProperty("sam") SAM("sam"); override fun toString(): String { return value } }
方案2:自定义Spring Converter(灵活适配复杂场景)
如果需要动态读取@JsonProperty注解的值,或者支持更复杂的转换逻辑,自定义Converter是更优选择:
序列化Converter(枚举转字符串)
import org.springframework.core.convert.converter.Converter import org.springframework.stereotype.Component import com.fasterxml.jackson.annotation.JsonProperty @Component class StudentNameToStringConverter : Converter<StudentName, String> { override fun convert(source: StudentName): String { val enumField = source.javaClass.getField(source.name) return enumField.getAnnotation(JsonProperty::class.java)?.value ?: source.name.lowercase() } }
反序列化Converter(字符串转枚举)
import org.springframework.core.convert.converter.Converter import org.springframework.stereotype.Component import com.fasterxml.jackson.annotation.JsonProperty @Component class StringToStudentNameConverter : Converter<String, StudentName> { override fun convert(source: String): StudentName { return StudentName.values().firstOrNull { enum -> val enumField = enum.javaClass.getField(enum.name) val jsonPropValue = enumField.getAnnotation(JsonProperty::class.java)?.value jsonPropValue.equals(source, ignoreCase = true) || enum.name.equals(source, ignoreCase = true) } ?: throw IllegalArgumentException("无效的StudentName: $source") } }
Spring会自动注册这些Converter,处理Query参数和枚举之间的双向转换:序列化时输出@JsonProperty指定的小写值,反序列化时兼容大小写或注解值输入。
验证效果
配置完成后,请求URL中的studentName参数会输出ram/sam,同时接收参数时也能正确识别RAM/ram等不同大小写的输入。
内容的提问来源于stack exchange,提问作者Sojan
相关产品推荐
相关产品推荐

