【问题标题】:Spring Boot convert Enum ignoring caseSpring Boot转换枚举忽略大小写
【发布时间】:2019-08-05 18:43:53
【问题描述】:

我有一个暴露 Rest API 的 spring-boot 应用程序。此 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 中寻找 active 而不是 ACTIVE

深入了解 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;
    }
}

【问题讨论】:

    标签: java spring spring-boot


    【解决方案1】:

    查看 Spring 项目的问题跟踪器可以找到 this 问题,它基本上要求公开 StringToEnumIgnoringCaseConverterFactory 类。
    不过,这似乎不会很快发生,因为this 仍在进行中。

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

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

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

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

    顺便说一句,这是对StringToEnumIgnoringCaseConverterFactory 的唯一引用,所以这是你唯一的希望; )(不要使用Reflection!忍住冲动)

    【讨论】:

    • 谢谢,它有效。同样正如one of the comments 中所建议的那样,最好创建自己的转换器而不是使用StringToEnumIgnoringCaseConverterFactory
    • @Abhishek 我不会走那条路。如果可行,请暂时坚持使用标准版本。
    猜你喜欢
    • 2018-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-26
    • 1970-01-01
    • 1970-01-01
    • 2018-01-11
    • 2011-06-04
    相关资源
    最近更新 更多