Десериализовать перечисление, игнорируя регистр в контроллере загрузки Spring

У меня есть конечная точка Spring Boot, у которой есть enum как параметр запроса:

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

И класс перечисления:

public enum ExampleEnum {
    FIRST,
    SECOND,
}

Если я передаю значение перечисления в верхнем регистре в конечную точку, оно хорошо десериализуется, но выдает ошибку для нижнего регистра:

java.lang.IllegalArgumentException: No enum constant 

Как десериализовать перечисление, игнорируя регистр в конечной точке Spring Boot Rest?

Этот вопрос не повторяется, потому что он связан с десериализацией параметров запроса.

Не дубликат, поскольку вопрос относится конкретно к параметрам строки запроса, которые обрабатываются иначе, чем атрибуты тела сообщения.

Dave 23.08.2019 16:57

ВЗДОХ - оба ответа неверны, и я не могу дать правильный ответ, так как вопрос был закрыт как дубликат людьми, которые не знают, о чем они говорят.

Dave 24.08.2019 05:09

@Dave Я изменил вопрос. Не могли бы вы повторно открыть под вопросом?

Justinas Jakavonis 24.08.2019 10:52

@Dave, пожалуйста, опубликуйте ответ

Justinas Jakavonis 30.01.2021 15:34
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
14
4
12 325
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Обновлено: Ответ ниже неверен. Вы должны определить собственный PropertyEditor и зарегистрировать его в Spring @InitBinder, который я объяснил в этом посте. Спасибо @Dave за указание на это в комментариях.


Spring Boot 2.0 использует Jackson 2.9 с функцией ACCEPT_CASE_INSENSITIVE_ENUMS. Вы должны иметь возможность включить его, установив

spring.jackson.mapper.ACCEPT_CASE_INSENSITIVE_ENUMS = true 

собственность согласно документы, Приложение A.

Добавлено свойство и objectMapper.enable (MapperFeature.ACCEPT_CASE_INSENSITIVE_EN‌ UMS); но все же получить java.lang.IllegalArgumentException: нет константы перечисления

Justinas Jakavonis 09.05.2018 16:11

Скорее всего, настраиваемый вами objectMapper не тот, который используется веб-слоем. Используйте свойства Spring Boot, как в моем примере, а затем проверьте. См. Класс Jackson2ObjectMapperBuilder.

Karol Dowbecki 09.05.2018 16:13

Я использовал как свойство загрузки: spring, так и включенное в пользовательском картографе объектов. Настраиваемая конфигурация ObjectMapper помечена как \ @Bean \ @Primary, поэтому она должна работать для всех слоев.

Justinas Jakavonis 09.05.2018 17:10

Джексон даже не заглянул сюда, потому что мы не десериализуем тело сообщения - Spring MVC вместо этого является параметром запроса преобразование. Для этой цели Spring использует зарегистрированные PropertyEditors DataBinder или, в противном случае, соответствующий TypeConverter из веб-службы ConversionService. Чтобы решить эту проблему, вы должны расширить PropertyEditorSupport и добавить аннотированный метод @InitBinder, который регистрирует его на вашем контроллере.

Dave 24.08.2019 05:13
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);
}

Все еще используете такие опции, да? должно было быть необязательным. orElse (null). См. Доклад Стюарта Марка youtube.com/watch?v=Ej0sss6cq14

ailveen 18.07.2018 12:19

затем используйте orElse (null) вместо if else

ailveen 19.07.2018 20:55

Вы можете сделать общий конвертер для всех перечислений

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()));
    }
}

А затем в любом из ваших контроллеров используйте его:

@InitBinder
    public void initBinder(WebDataBinder dataBinder) {
        dataBinder.registerCustomEditor(YourEnum.class, new EnumConverter(YourEnum.class));
    }

Другие вопросы по теме