【问题标题】:How to fix JSON parse error in @requestbody and Enum value?如何修复 @requestbody 和 Enum 值中的 JSON 解析错误?
【发布时间】:2020-10-27 13:38:53
【问题描述】:

我有两种方法:

  1. “JSON 正文”请求
  2. “表单参数”请求
@RequestMapping(value = "/orders.json", consumes = { "application/json" }, method = RequestMethod.POST)
@Override
public ResponseEntity<Void> createOrder(@Valid @RequestBody OrderCreateDTO orderCreateDTO) {
    return doCreateOrder(orderCreateDTO);
}

@RequestMapping(value = "/orders.json", consumes = { "application/x-www-form-urlencoded" }, method = RequestMethod.POST)
public ResponseEntity<Void> createOrderForm(@Valid @ModelAttribute OrderCreateDTO orderCreateDTO) {
    return doCreateOrder(orderCreateDTO);
}

第二种方法很好,但是第一种方法有问题。 在该方法中,当我发送枚举字段时,出现以下错误:

JSON parse error: Cannot construct instance of `......service.dto.EuropeanLanguageEnumTypeDTO`, problem: Unexpected value 'EN'; nested exception is com.fasterxml.jackson.databind.exc.ValueInstantiationException: Cannot construct instance of `......service.dto.EuropeanLanguageEnumTypeDTO`, problem: Unexpected value 'EN'\n at [Source: (PushbackInputStream); line: 6, column: 17] (through reference chain: ......service.dto.OrderCreateDTO[\"language\"])

Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot construct instance of `.......service.dto.EuropeanLanguageEnumTypeDTO`, problem: Unexpected value 'EN'; nested exception is com.fasterxml.jackson.databind.exc.ValueInstantiationException: Cannot construct instance of `......service.dto.EuropeanLanguageEnumTypeDTO`, problem: Unexpected value 'EN'
 at [Source: (PushbackInputStream); line: 6, column: 17] (through reference chain: ......service.dto.OrderCreateDTO["language"])]

EuropeanLanguageEnumTypeDTO.java

public enum EuropeanLanguageEnumTypeDTO {
  
  BG("bg"),
  
  HR("hr"),
  
  CS("cs"),
  
  EN("en");

  private String value;

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

  @JsonValue
  public String getValue() {
    return value;
  }

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

  @JsonCreator
  public static EuropeanLanguageEnumTypeDTO fromValue(String value) {
    for (EuropeanLanguageEnumTypeDTO b : EuropeanLanguageEnumTypeDTO.values()) {
      if (b.value.equals(value)) {
        return b;
      }
    }
    throw new IllegalArgumentException("Unexpected value '" + value + "'");
  }
}

另外,我还有另一个组件来转换枚举,但它只适用于“表单”请求:

@Component
public class EuropeanLanguageEnumConverter implements Converter<String, EuropeanLanguageEnumTypeDTO> {

    @Override
    public EuropeanLanguageEnumTypeDTO convert(String value) {
        return EuropeanLanguageEnumTypeDTO.fromValue(value);
    }

}

工作 JSON 和不工作的示例:

成功

{
    "language": "en"
}

失败

{
    "language": "EN"
}

我需要使用大小写。
我搜索了很多,尝试了一些不同的方法,例如jackson.mapper.ACCEPT_CASE_INSENSITIVE_ENUMS: true,但没有奏效,请帮我解决这个问题。

附:由于某种原因,我无法在 ENUM 类中进行编辑,因为它将使用 openAPI 生成。

【问题讨论】:

    标签: java json spring enums


    【解决方案1】:

    第二种解决方案:您使用@JsonCreator 的方法是可以的,但需要进行一些小改动。将以下方法放入您的枚举中:

    @JsonCreator
    public static EuropeanLanguageEnumTypeDTO forValue(String value) {
        return Stream.of(EuropeanLanguageEnumTypeDTO.values())
            .filter(enumValue -> enumValue.name().equals(value.toUpperCase()))
            .findFirst()
            .orElseThrow(IllegalArgumentException::new);
    }
    

    【讨论】:

      【解决方案2】:

      答案很简单,尝试直接放入你的 DTO 枚举值而不是字符串。 您不需要额外的映射器。

      【讨论】:

      • 感谢您的回答,很遗憾,我无法更改我的 DTO,因为它是由开放 API 生成的
      • 好的,你可以使用 String 类中的方法 -> .toLowerCase 或 toUpperCase 然后转换为枚举
      • 你能在这个答案中向我解释更多吗?
      • 我添加了第二种可能的解决方案。
      猜你喜欢
      • 2021-06-02
      • 1970-01-01
      • 2023-03-22
      • 1970-01-01
      • 1970-01-01
      • 2019-06-09
      • 2020-11-29
      • 1970-01-01
      • 2020-12-08
      相关资源
      最近更新 更多