【问题标题】:Spring Boot - String to Enum conversion accepts value and index of the enum. How to reject numeric inputs and only accept enum value?Spring Boot - 字符串到枚举的转换接受枚举的值和索引。如何拒绝数字输入并只接受枚举值?
【发布时间】:2020-07-04 14:20:05
【问题描述】:

我有一些简单的枚举,如下所示。

public enum Status {
  ACTIVE,
  PASSIVE;

  private Status() {
  }
}

我的 REST 服务输入对象中有一个字符串状态字段。

当服务收到两个请求时,它会将其转换为 PASSIVE。

案例 1 状态 = 1

{
    "name": "Walter",
    "surname": "White"
    "status": "1"
}

案例 2 status = "被动"

{
    "name": "Walter",
    "surname": "White"
    "status": "PASSIVE"
}

我不希望默认转换器接受数字输入(案例 1)。我的意思是我不希望它通过使用枚举的索引将 1 转换为 PASSIVE。

我希望它只接受非数字值,因为它在 CASE 2 中。

还考虑到我有很多这样的枚举,我想将限制应用于我的所有枚举。

我怎样才能使它像上面解释的那样工作?

【问题讨论】:

    标签: java spring spring-boot enums


    【解决方案1】:

    更新:

    默认情况下,Number for Enum 通过映射枚举序数来反序列化。在ObjectMapper中添加配置DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS为true,默认为false。

    @Configuration
    public class JacksonConfig {
    
      @Bean
      @Primary
      public ObjectMapper configureObjectMapper() {
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.configure(DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS, true);
        return objectMapper;
      }
    }
    

    另一种方法是为枚举验证编写自定义注解。并在具有可能值的字段上使用它

    @EnumNamePattern
    private Status status;
    

    用于枚举验证的自定义注解

    @Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE})
    @Retention(RUNTIME)
    @Documented
    @Constraint(validatedBy = EnumNamePatternValidator.class)
    public @interface EnumNamePattern {
        String message() default "invalid";
        Class<?>[] groups() default {};
        Class<? extends Payload>[] payload() default {};
    }
    

    并为注解编写验证器

    public class EnumNamePatternValidator implements ConstraintValidator<EnumNamePattern, Enum<?>> {
        @Override
        public boolean isValid(Enum<?> value, ConstraintValidatorContext context) {
            if (value == null) return true;
            return Arrays.stream(Status.values()).anyMatch(e -> e.name().equals(value.name()));
        }
    }
    

    【讨论】:

    • 如果我使用此解决方案,当将新值添加到枚举时,我将不得不更新引用枚举的所有参数的正则表达式。是否有一种通用的方法来拒绝所有枚举的数值。这就是为什么我不想应用它。因为它是不可维护的。我最好应用一个更简单的解决方案。谢谢您的回答。我很高兴,但我仍在寻找不同的解决方案。
    • 顺便说一句,我想在 Strin 到 Enum 转换期间拒绝值。我不需要过滤枚举值。在我的示例中,我想停止将 1 转换为 PASSIVE 的内容。
    • @cavo 我认为重置配置是最简单的解决方案。
    • JacksonConfig 是我一直在寻找的。我还使用全局异常处理程序来返回异常的根本原因。非常感谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-23
    相关资源
    最近更新 更多