При передачи boolean через postman записывается String

кейс:

В Postman, в строковое значение (String), передаю bolean(true или false). Все отлично отрабатывает c неправильными по типу данными, т.к. становится String = "false" ( как я понимаю это из-за протокола HTTP все приводится к строковым значениям).

JSON

{
 "str": false
}

НО:

Мне надо, чтобы была ошибка, т.к. я передал булевое значение, false (без кавычек).

Как вариант решения:

Есть метод с параметром(@RequestBody @Valid Request request){};.

клас Request

@Data
public class Request {
    private String str;
}

Я сделал свой валидатор над полем String (в классе Request). Если в это поле(String) записывается true или false, то @Valid кидает ошибку.

Мне кажется можно, как-то проще сделать...

Вопрос:

Есть ли способ легче это написать? может одной аннотацией или несколько строчек кода. Как можно оптимизировать?


Ответы (1 шт):

Автор решения: Roman-Stop RU aggression in UA

Это известное ограничение json парсера jackson, который используется в spring по-умолчанию. Суть проблемы в том, что парсер автоматически делает преобразование объекта в строку, хотя у него и есть контекст, т.е. тип, который ожидается.

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

// ForceStringDeserializer.java
public class ForceStringDeserializer extends JsonDeserializer<String> {
    @Override
    public String deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
        if (jsonParser.getCurrentToken() != JsonToken.VALUE_STRING) {
            throw deserializationContext.wrongTokenException(
                jsonParser, String.class, JsonToken.VALUE_STRING,
                "Attempted to parse non-string to string but this is forbidden");
        }
        return jsonParser.getValueAsString();
    }
  }


// MyConfig.java
@Configuration
class MyConfig {
  @Bean
  public Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder() {
    return new Jackson2ObjectMapperBuilder()
        .serializerByType(String.class, new ForceStringDeserializer());
  }
}
→ Ссылка