Spring Boot转换Enum忽略大小写

时间:2019-03-14 18:39:27

标签: java spring spring-boot

我有一个Spring-boot应用程序,它正在公开Rest API。该API接受枚举batchStatus的列表作为查询参数。 batchStatus用于根据批次的状态过滤所有批次。

尝试调用此rest api时,出现以下错误

{
  "timestamp": 1552587376808,
  "status": 400,
  "error": "Bad Request",
  "message": "Failed to convert value of type 'java.lang.String[]' to required type 'java.util.List'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [@io.swagger.annotations.ApiParam @javax.validation.Valid @org.springframework.web.bind.annotation.RequestParam com.netshell.test.spring.conversion.rest.api.model.BatchStatus] for value 'active'; nested exception is java.lang.IllegalArgumentException: No enum constant com.netshell.test.spring.conversion.rest.api.model.BatchStatus.active",
  "path": "/batch/status"
}

Spring正在BatchStatus中寻找活动,而不是活动

深入研究Spring ConversionService,我发现了两个转换器
1. StringToEnumConverterFactory(来自spring-core)
2. StringToEnumIgnoringCaseConverterFactory(来自spring-boot)

spring-boot中是否存在强制使用第二个转换器的机制?

进一步的调试显示,两个转换器都已向ConversionService注册,但是multiple instances of conversionService中的每个转换器具有不同数量的转换器。在这种情况下,spring如何选择要使用的conversionService?

枚举BatchStatus如下创建

public enum BatchStatus {
    ACTIVE("active"),
    FAILED("failed"),
    HOLD("hold");

    private String value;
    BatchStatus(String value) {
        this.value = value;
    }

    @Override
    @JsonValue
    public String toString() {
        return String.valueOf(value);
    }

    @JsonCreator
    public static BatchStatus fromValue(String text) {
        for (BatchStatus b : BatchStatus.values()) {
            if (String.valueOf(b.value).equals(text)) {
                return b;
            }
        }
        return null;
    }
}

1 个答案:

答案 0 :(得分:1)

通过查看Spring项目的问题跟踪器,您可以找到this问题,该问题基本上要求将StringToEnumIgnoringCaseConverterFactory类公开。
但是,由于this仍在进行中,因此似乎不会很快发生。

您可以尝试通过Converter配置WebMvcConfigurer#addFormatters

@Configuration
class CustomWebMvcConfigurer implements WebMvcConfigurer {
    @Override
    public void addFormatters(final FormatterRegistry registry) {
        ApplicationConversionService.configure(registry);
    }
}

ApplicationConversionService#configure将通过调用StringToEnumIgnoringCaseConverterFactory方法为您注册addApplicationConverters

/** Spring Framework code */
public static void addApplicationConverters(ConverterRegistry registry) {
    ...
    registry.addConverterFactory(new StringToEnumIgnoringCaseConverterFactory());
}

顺便说一句,这是对StringToEnumIgnoringCaseConverterFactory的唯一引用,因此这是您唯一的希望; )(不要使用Reflection!抵制这种冲动)