Как правильно обрабатывать Jackson InvalidFormatException?

В настоящее время я борюсь с десериализацией Java JSON с Джексоном следующим образом:

Я хочу обработать и десериализовать ответ JSON. Я возвращаюсь из веб-службы и конвертирую ответ в POJO с помощью Jackson. Это работает отлично в большинстве случаев, пока ответ, который я получаю, содержит атрибуты JSON в правильном формате.

Однако, поскольку веб-служба и данные , полученные вами, не поддаются контролю, я не могу полагаться на данные, всегда находящиеся в правильном формате.

Позволь мне привести пример:

В моем POJO есть поле java.util.Date, а ответ JSON содержит свойство, содержащее строку datetime. Джексон попытается разобрать строку и преобразовать ее в Date. Если формат даты матчей в ObjectMapper's DateFormat (ObjectMapper.setDateFormat(...)), все в порядке. Если формат отличается, я получаю InvalidFormatException.

Проблема в том, что датаформат, отправленный из службы, может отличаться. Я могу получить даты, отформатированные как 2014-11-02T00:00:00Z, но я также могу получить даты, отформатированные как 2014-11 (идентификация всего одного месяца вместо целого дня и времени).

Я знаю, я могу написать собственный десериализатор, который мог бы позаботиться об этом конкретном случае и правильно обработать даты с разными форматами дат. Но поскольку это только устранит проблемы с Dates, но не с потенциальными другими типами данных, я ищу более общий подход. (Что произойдет, например, если я ожидаю Double и получите буквенно-цифровую строку?)

Я хотел бы иметь возможность игнорировать все случаи, в которых происходит InvalidFormatException, и определять значение по умолчанию (например, null) в соответствующее поле POJO.

И это было бы очень полезно для меня, если, несмотря на возвращение недействительного dateformat или любое другое InvalidFormatException, остальная часть JSON все равно будет десериализована в POJO.

Это возможно с Джексоном?

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

Ответ 1

Не уверен, что это лучшая практика, у меня мало опыта работы с Джексоном.

Вы можете добавить DeserializationProblemHandler к ObjectMapper, чтобы определить, что происходит, когда десериализатор встречает странную строку или странное число.

В вашем случае вы можете установить обработчик таким образом, чтобы при обнаружении непризнанного формата вместо того, чтобы бросать InvalidFormatException, он просто возвращает null:

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.addHandler(new DeserializationProblemHandler() {
    @Override
    public Object handleWeirdStringValue(DeserializationContext ctxt, Class<?> targetType, String valueToConvert, String failureMsg) throws IOException {
        return null;
    }

    @Override
    public Object handleWeirdNumberValue(DeserializationContext ctxt, Class<?> targetType, Number valueToConvert, String failureMsg) throws IOException {
        return null;
    }
});