1

I have the following endpoint

@GetMapping(value = "/mypath/{mychoice}")
public ResponseClass generateEndpoint(
        @PathVariable("mychoice") FormatEnum format,
    )  {

...

and the following enum annotated with Jackson

@JsonNaming(PropertyNamingStrategies.KebabCaseStrategy.class)
public enum Format {
    AVRO,
    ORC,
    PARQUET,
    PROTOBUF
}

I hoped, @JsonNaming annotation will tell swagger to display cases in lowercase, but it doesn't

enter image description here

Adding @JsonProperty to each case also doesn't help.


It also doesn't accept lowercase URL with error

org.springframework.beans.TypeMismatchException: Failed to convert value of type 'java.lang.String' to required type 'FormatEnum'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [@org.springframework.web.bind.annotation.RequestParam FormatEnum] for value 'avro'; nested exception is java.lang.IllegalArgumentException: No enum constant FormatEnum.avro

Setting

 spring.jackson.mapper.ACCEPT_CASE_INSENSITIVE_ENUMS = true 

has no effect (and is true in code).

Looks like it just doesn't use Jackson to deserialize enum!

samabcde
  • 6,988
  • 2
  • 25
  • 41
Dims
  • 47,675
  • 117
  • 331
  • 600
  • Please check if [my previous answer](https://stackoverflow.com/questions/67210546/how-to-convert-multiple-values-to-enum-in-requestparm/67214002#67214002) help. – samabcde Mar 18 '22 at 15:28
  • Is there any solution for all enums? – Dims Mar 18 '22 at 17:45

1 Answers1

1

Answering the part for serializing Enum case insensitive

The reason why setting spring.jackson.mapper.ACCEPT_CASE_INSENSITIVE_ENUMS=true is not working can be found in Konstantin Zyubin's answer.

And inspired from above answer, we can have a more generic approach to handle case insensitive enums in request parameter.

Converter class

import org.springframework.core.convert.converter.Converter;

public class CaseInsensitiveEnumConverter<T extends Enum<T>> implements Converter<String, T> {
    private Class<T> enumClass;

    public CaseInsensitiveEnumConverter(Class<T> enumClass) {
        this.enumClass = enumClass;
    }

    @Override
    public T convert(String from) {
        return T.valueOf(enumClass, from.toUpperCase());
    }
}

Add in configuration

import com.example.enums.EnumA;
import com.example.enums.EnumB;
import com.example.enums.FormatEnum;
import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.List;

@Configuration
public class AppConfig implements WebMvcConfigurer {

    @Override
    public void addFormatters(FormatterRegistry registry) {
        List<Class<? extends Enum>> enums = List.of(EnumA.class, EnumB.class, FormatEnum.class);
        enums.forEach(enumClass -> registry.addConverter(String.class, enumClass,
                      new CaseInsensitiveEnumConverter<>(enumClass)));
    }
}

Related: Jackson databind enum case insensitive

samabcde
  • 6,988
  • 2
  • 25
  • 41
  • 1
    Yes, I did this way. I found example class existed in earlier versions of Spring (called `StringToEnumConverterFactory`). Also I have an explanation why isn't it work with Jackson: because enum value in URL IS NOT A JSON AT ALL (it is not quoted for example). It will not work in a body too, unless it is a valid JSON (for ex quoted or wrapped into other JSON). – Dims Mar 21 '22 at 20:32