首页 > 解决方案 > Spring Boot - 字符串到枚举的转换接受枚举的值和索引。如何拒绝数字输入并只接受枚举值?

问题描述

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

public enum Status {
  ACTIVE,
  PASSIVE;

  private Status() {
  }
}

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

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

案例 1 状态 = 1

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

案例 2 状态 = “被动”

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

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

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

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

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

标签: javaspringspring-bootenums

解决方案


更新:

默认情况下,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()));
    }
}

推荐阅读