Ограничить строковый тип данных только строковыми типами для тела запроса в Spring boot 2.4 (Jackson)

Я создал свой запрос POJO следующим образом

@JsonInclude(JsonInclude.Include.NON_NULL)
public class Notification {

    @NotNull
    private String clientId;
    private String userId;  
    @NotNull
    private String requestingService;
    @NotNull
    private String message;
    @NotNull
    private String messageType;

когда я отправляю тело запроса, как показано ниже, он работает нормально.

{
   "clientId":"9563",
    "userId":"5855541",
    "requestingService":"cm-dm-service",
    "message":"Document Created",
    "messageType":"user-msg"
}

Но когда я отправил, как показано ниже

{
   "clientId":"9563",
    "userId":true,
    "requestingService":"cm-dm-service",
    "message":"Document Created",
    "messageType":"user-msg"
}

Вот мой контроллер

public ResponseEntity<Status> createNotification(@RequestBody @Valid Notification notification,
            BindingResult bindingResult, HttpServletRequest request) throws AppException {

Ожидается: выдать ошибку

Фактически: преобразование истинного значения для userId в строку Джексоном.

пожалуйста, дайте мне знать, есть ли способ добиться ожидаемого поведения

Что такое **true**?

burm87 24.12.2020 16:06

Пожалуйста, проверьте stackoverflow.com/questions/12546810/…

silentsudo 24.12.2020 17:11

@burm87 отредактировал. На самом деле это логический тип

M. Akhil 24.12.2020 17:27
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
3
3
1 025
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

Джексон NumberDeserializers.BooleanDeserializer запрограммирован на преобразование логического значения в строку.

Мы можем переопределить десериализатор нашим, предотвратить преобразование и вместо этого генерировать исключение.

Я могу привести вам пример, вы пытаетесь внедрить его в свою постановку задачи.

  1. Создайте логический класс десериализации

    public class MyDeser extends JsonDeserializer {
        @Override
        public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
            JsonToken t = p.getCurrentToken();
            if (t.isBoolean()) {
                throw new Exception();
            }
            else if (t.isNumeric()) {
                throw new Exception();
            }
            else if (t == JsonToken.VALUE_STRING) {
                return p.getValueAsString();
            }
            return null;
        }
    }

  1. Теперь внедрите десериализатор в наше приложение.

    @SpringBootApplication
     @Configuration
     public class Application {
         @Bean
         public SimpleModule injectDeser() {
             return new SimpleModule().addDeserializer(String.class, new MyDeser());
         }
         public static void main(String[] args) {
             SpringApplication.run(Application.class, args);
         }
     }

Здесь t.asString() вернул null. Поэтому я использовал p.getValueAsString(); а также изменил тип возвращаемого значения на String. общедоступная десериализация строки (.....). После этого код работает нормально, как и ожидалось. Спасибо Шринивасу Рагхавану.

M. Akhil 28.12.2020 10:36

Привет, я отредактировал это, как вы сказали. Если это решение, о котором вы просили, примите этот ответ как решение, чтобы оно было полезно и для других. Спасибо

srini 28.12.2020 16:19

По умолчанию com.fasterxml.jackson.databind.deser.std.StringDeserializer принимает скалярные значения. В этом случае вы можете реализовать собственный десериализатор и выдать исключение:

class StrictStringDeserializer extends StringDeserializer {
    @Override
    public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        JsonToken token = p.currentToken();
        if (token.isScalarValue()) {
            ctxt.reportInputMismatch(String.class, "%s is not a `String` value!", token.toString());
            return null;
        }
        return super.deserialize(p, ctxt);
    }
}

Для регистрации используйте SimpleModule:

SimpleModule strictModule = new SimpleModule();
strictModule.addDeserializer(String.class, new StrictStringDeserializer());

ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(strictModule);

Чтобы узнать, как это сделать в Spring, прочитайте: Настройте Jackson ObjectMapper.

Если вы хотите изменить его только для одного поля: userId используйте аннотацию JsonDeserialize:

@JsonDeserialize(using = StrictStringDeserializer.class)
private String userId;

Смотрите также:

  • Можно ли использовать собственный сериализатор/десериализатор для типа дефолт весной?

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