SpringBoot 其余验证不会因错误的枚举输入而失败

问题描述 投票:0回答:1

我有一个 SpringBoot 休息 POST 端点,在正文中我 POST 一个枚举值。此调用不会因为输入错误的值而失败。我希望其余调用失败,而不是为无法反序列化的值返回 null。

我已尝试使用以下自定义 ObjectMapper 配置,但我作为枚举放置的任何错误输入都会反序列化为 null。

@Bean
@Primary
public ObjectMapper customJsonObjectMapper() {
    Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
    ObjectMapper objectMapper = builder.build();
    objectMapper.configure(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL, false);
    SimpleModule module = new SimpleModule();
    objectMapper.registerModule(module);
    return objectMapper;
}

例如,如果我有枚举:

public enum CouponOddType {
  BACK("back"),
    LAY("lay");

  private String value;

  CouponOddType(String value) {
    this.value = value;
  }

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

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

请求映射到的 dto:

    @ApiModel(description = "Filter used to query coupons. Filter properties are combined with AND operator")
@Validated
@javax.annotation.Generated(value = "io.swagger.codegen.v3.generators.java.SpringCodegen", date = "2020-07-07T13:12:58.487+02:00[Europe/Ljubljana]")
public class CouponQueryFilter   {
  
  @JsonProperty("statuses")
  @Valid
  private List<CouponStatus> statuses = null;

  @JsonProperty("oddTypes")
  @Valid
  private List<CouponOddType> oddTypes = null;

  public CouponQueryFilter statuses(List<CouponStatus> statuses) {
    this.statuses = statuses;
    return this;
  }

  public CouponQueryFilter addStatusesItem(CouponStatus statusesItem) {
    if (this.statuses == null) {
      this.statuses = new ArrayList<>();
    }
    this.statuses.add(statusesItem);
    return this;
  }

  /**
   * Get statuses
   * @return statuses
  **/
  @ApiModelProperty(value = "")
      @Valid
    public List<CouponStatus> getStatuses() {
    return statuses;
  }

  public void setStatuses(List<CouponStatus> statuses) {
    this.statuses = statuses;
  }

  public CouponQueryFilter oddTypes(List<CouponOddType> oddTypes) {
    this.oddTypes = oddTypes;
    return this;
  }

  public CouponQueryFilter addOddTypesItem(CouponOddType oddTypesItem) {
    if (this.oddTypes == null) {
      this.oddTypes = new ArrayList<>();
    }
    this.oddTypes.add(oddTypesItem);
    return this;
  }

  /**
   * Get oddTypes
   * @return oddTypes
  **/
  @ApiModelProperty(value = "")
      @Valid
    public List<CouponOddType> getOddTypes() {
    return oddTypes;
  }

  public void setOddTypes(List<CouponOddType> oddTypes) {
    this.oddTypes = oddTypes;
  }

}

在 POST 请求中,我将枚举值放入 json 数组中:

{
 
    "statuses": [
       "wrong value"
    ],
    "oddTypes": [
       "wrong value"
    ]
}

我希望这种类型的请求会导致 HTTP 404 错误,而不是反序列化为 null。

spring-boot rest validation enums
1个回答
1
投票

在这种情况下,Jackson 实际上按照预期行事,并且您的反序列化逻辑存在问题。最终,您希望错误的枚举值引发错误并将该错误返回给用户。这实际上是 spring 和 Jackson 的默认行为,并且会导致

HTTP 400 BAD REQUEST
错误。 IMO 这是返回的适当错误(不是 404),因为用户提供了错误的输入。

除非有特定原因需要您在枚举类中实现自定义

@JsonCreator
,否则我会删除它。这里发生的事情是 Jackson 被告知使用此方法将字符串转换为枚举值,而不是使用默认方法。当传递的文本不是枚举的有效值时,您将返回
null
,这会导致该值反序列化为 null。

一个快速修复方法是删除

JsonCreator
并允许 Jackson 使用其默认行为来处理枚举。在大多数情况下,您添加的额外属性方法是不必要的

public enum CouponOddType {
  BACK("back"),
    LAY("lay");

  private String value;

  CouponOddType(String value) {
    this.value = value;
  }
}

如果您因其他原因需要保留创建者,则需要添加业务逻辑来确定数组中的任何

enum
值是否计算为
null

private Response someSpringRestEndpoint(@RequestBody CouponQueryFilter filter){
  if (filter.getOddTypes() != null && filter.getOddTypes().contains(null){
    throw new CustomException()
  }

  if (filter.getStatuses() != null && filter.getStatuses().contains(null){
    throw new CustomException()
  }

  //... other business logic
}

© www.soinside.com 2019 - 2024. All rights reserved.