Какие ошибки могут возникнуть при работе с JSON в Java и как их обработать
Что проверяют
Работали ли вы с Jackson дальше readValue и знаете ли, какие исключения он бросает и почему. Следом часто спрашивают, как это выглядит в Spring и что получит клиент при кривом теле запроса.
Как отвечать
Разберите иерархию Jackson 2, на нём большинство проектов. Корень JsonProcessingException, проверяемое исключение, от него идут:
JsonParseException: битый синтаксис, лишняя запятая, незакрытая скобка;MismatchedInputException: не та структура, например массив вместо объекта. Его наследникInvalidFormatExceptionпро значение:"abc"в полеintили дата не в том формате;UnrecognizedPropertyException: в JSON есть поле, которого нет в классе. Голыйnew ObjectMapper()на этом падает,FAIL_ON_UNKNOWN_PROPERTIESвключён по умолчанию, аObjectMapperиз Spring Boot эту опцию отключает;InvalidDefinitionException: проблема в классе, а не в данных. Нет подходящего конструктора илиLocalDateбез модуляjackson-datatype-jsr310(Spring Boot подключает его сам).
При сериализации частая беда это циклические ссылки между сущностями JPA и бесконечная рекурсия. Лечится DTO, @JsonIgnore или парой @JsonManagedReference и @JsonBackReference.
Про отсутствующие поля: по умолчанию Jackson ставит null или ноль и не жалуется. @JsonProperty(required = true) проверяется только для параметров конструктора с @JsonCreator, для сеттеров нет. Надёжнее Bean Validation: @NotNull плюс @Valid на входе контроллера.
В Spring кривое тело превращается в HttpMessageNotReadableException и по умолчанию даёт 400, формат ответа задают в @RestControllerAdvice. Плюсом будет знать, что в Jackson 3 пакеты переехали в tools.jackson, а исключения стали непроверяемыми.
Где спотыкаются
Ловят общий Exception и пишут в лог «ошибка JSON». Клиент получает 500 вместо 400, а по логу непонятно, что не так.
Думают, что required = true работает везде, и удивляются, когда объект без обязательного поля спокойно десериализовался.
Не отличают ошибку данных от ошибки маппинга. InvalidDefinitionException означает баг в коде, и отвечать на него клиенту кодом 400 неправильно.