21

I have Spring Boot endpoint which has enum as query param:

@GetMapping("/example")
public List<Example> getByEnum(@RequestParam(name = "exampleEnum", required = false) ExampleEnum exampleEnum) {
    // code
}

And enum class:

public enum ExampleEnum {
    FIRST,
    SECOND,
}

If I pass uppercase enum value to the endpoit, it deserializes well but it throws error for lowercase:

java.lang.IllegalArgumentException: No enum constant 

How to deserialize enum ignoring case in Spring Boot Rest endpoint?

This question is not duplicate because it's related to query param deserialization.

Justinas Jakavonis
  • 8,220
  • 10
  • 69
  • 114
  • Not a duplicate as the question refers specifically to query string parameters which are handled differently to attributes of a post body. – Dave Aug 23 '19 at 14:57
  • 3
    SIGH - both answers are wrong and I am not able to provide a correct answer as the question has been closed as a duplicate by people who don't know what they are talking about. – Dave Aug 24 '19 at 03:09
  • @Dave I have modified question. Could you press reopen below the question? – Justinas Jakavonis Aug 24 '19 at 08:52

4 Answers4

41

EDIT: The answer below is incorrect. You have to define a custom PropertyEditor and register it with Spring @InitBinder which I explained in this post. Thanks to @Dave for pointing this out in the comments.


Spring Boot 2.0 is using Jackson 2.9 which has ACCEPT_CASE_INSENSITIVE_ENUMS feature. You should be able to enable it by setting

spring.jackson.mapper.ACCEPT_CASE_INSENSITIVE_ENUMS = true 

property as per docs, Appendix A.

Karol Dowbecki
  • 43,645
  • 9
  • 78
  • 111
  • 10
    Added property and objectMapper.enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS); but still get java.lang.IllegalArgumentException: No enum constant – Justinas Jakavonis May 09 '18 at 14:11
  • Most likely the `objectMapper` you are configuring is not the one used by web layer. Use the Spring Boot properties as in my example and then check. See `Jackson2ObjectMapperBuilder` class. – Karol Dowbecki May 09 '18 at 14:13
  • 2
    I have used both: spring boot property and enabled on custom object mapper. Custom ObjectMapper config is marked as \@Bean \@Primary so it should work for all layers. – Justinas Jakavonis May 09 '18 at 15:10
  • 11
    Jackson doesn't even get a look-in here because we are not deserializing a message body - Spring MVC is instead _converting_ a request param. For this purpose Spring uses the DataBinder's registered PropertyEditors or, failing that, a matching TypeConverter from the web ConversionService. To resolve this issue you should extend PropertyEditorSupport and add an @InitBinder annotated method which registers it to your controller. – Dave Aug 24 '19 at 03:13
6
import com.fasterxml.jackson.annotation.JsonCreator;
import java.util.Arrays;
import java.util.Optional;

public enum ExampleEnum {
    FIRST,
    SECOND;

    @JsonCreator
    public static ExampleEnum setValue(String key) {
        return Arrays.stream(ExampleEnum.values())
            .filter(exampleEnum -> exampleEnum.toString().equals(key.toUpperCase()))
            .findAny()
            .orElse(null);
}
Jacob van Lingen
  • 8,989
  • 7
  • 48
  • 78
GolamMazid Sajib
  • 8,698
  • 6
  • 21
  • 39
2

You can make generic converter for all enums

package ru.grancall.kb.logging.service.dto.converter;

import lombok.AllArgsConstructor;
import org.apache.commons.lang3.EnumUtils;
import java.beans.PropertyEditorSupport;

@AllArgsConstructor
public class EnumConverter extends PropertyEditorSupport {
    private Class type;

    public void setAsText(String text) {
        setValue(EnumUtils.getEnum(type, text.toUpperCase()));
    }
}

And then in any of your Controllers use it:

@InitBinder
    public void initBinder(WebDataBinder dataBinder) {
        dataBinder.registerCustomEditor(YourEnum.class, new EnumConverter(YourEnum.class));
    }
ema
  • 891
  • 11
  • 21
2

If you want to get ALL your enums handled case-insensitively you can use Spring's ApplicationConversionService.

You only have to register it with the following little Configuration (see baeldung):

@Configuration
public class EnumMappingConfig implements WebMvcConfigurer {
    @Override
    public void addFormatters(FormatterRegistry registry) {
        ApplicationConversionService.configure(registry);
    }
}
Fable
  • 371
  • 1
  • 4
  • 11