Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to fix JSON parse error in @requestbody and Enum value?

I've two methods:

  1. "JSON Body" request
  2. "Form param" request
@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);
}

The second method is fine, but there is an issue with the first. In the method, when I sending an enum field, I got the following errors:

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 + "'");
  }
}

Also, I've another component, to convert enum, but it just works only with 'form' request:

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

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

}

Example of working JSON and not working:

success:

{
    "language": "en"
}

fail:

{
    "language": "EN"
}

I need to work with upper and lower case.
I search a lot and tried some different ways, such as jackson.mapper.ACCEPT_CASE_INSENSITIVE_ENUMS: true, but didn't work, please help me with this issue.

P.s. for some reason I can't edit inside ENUM class, because it will generate with openAPI.

like image 281
Mohammadreza Yektamaram Avatar asked Aug 31 '25 03:08

Mohammadreza Yektamaram


1 Answers

Second solution: the method which you use with @JsonCreator is ok but it needs small changes. Put to your enum the method below:

@JsonCreator
public static EuropeanLanguageEnumTypeDTO forValue(String value) {
    return Stream.of(EuropeanLanguageEnumTypeDTO.values())
        .filter(enumValue -> enumValue.name().equals(value.toUpperCase()))
        .findFirst()
        .orElseThrow(IllegalArgumentException::new);
}
like image 76
Mateusz Avatar answered Sep 02 '25 15:09

Mateusz