Могу ли я игнорировать исключение MismatchedInputException в ObjectMapper?

Я использую класс Jackson ObjectMapper так:

objectMapper.treeToValue(jsonNode, MyClass.class)

где jsonNode - это экземпляр JsonNode.

Когда я звоню treeToValue(), я получаю MismatchedInputException с сообщением

Cannot deserialize instance of com.example.MyField` out of START_OBJECT token

потому что MyField определяется как строка внутри MyClass, но это объект JSON внутри переменной jsonNode. Я полностью согласен с jsonNode, имеющим несоответствующий тип для одного из его полей, но я бы предпочел, чтобы ObjectMapper просто не пытался сериализовать это поле и игнорировать его вместо того, чтобы бросать MismatchedInputException.

Я пробовал использовать

objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

но это просто игнорирует отсутствующие поля, это не делает ничего, чтобы предотвратить MismatchedInputException для существующего поля.

Я не думаю, что вы можете игнорировать его с точки зрения функциональности, если вам не требуется поле; в этом случае вы могcatch в MismatchedInputException и ничего не делаете. Однако я не уверен, что это именно то, чего вы хотите достичь.

Taco タコス 16.10.2018 16:10

@PerpetualJ Верно, я все еще хочу, чтобы все остальные поля были сериализованы. Похоже, если я поймаю MismatchedInputException, он просто пропустит весь процесс сериализации

user2121620 16.10.2018 16:13

см. этот вопрос и несколько хитрых ответов: stackoverflow.com/questions/4783421/…

diginoise 16.10.2018 16:19

@ user2121620 Я считаю, что он завершит процесс сериализации, если вы поймаете исключение.

Taco タコス 16.10.2018 16:48
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
4
4
2 506
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

В сообщении, на которое ссылается diginoise, вы должны взглянуть на этот ответ:

https://stackoverflow.com/a/40972234/9343066

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

Вы можете рекурсивно удалить недопустимые поля и повторить попытку. Вот что я придумал (можно упростить в зависимости от ваших потребностей в ведении журнала и обработке исключений).

public class YourClass {

    private static final Logger LOGGER = Logger
            .getLogger(YourClass.class.getName());

    public final static ObjectMapper mapper = new ObjectMapper().configure(
            DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

    public static <T> T toTypedObject(Class<T> type, JsonNode tree) {
        return toTypedObject(type, tree, true);
    }

    private static <T> T toTypedObject(Class<T> type, JsonNode tree,
            boolean topLevel) {

        T object;

        try {
            object = mapper.treeToValue(tree, type);
        } catch (MismatchedInputException e) {
            String originalTree = tree.toString();
            object = toTypedObject(type, tree, originalTree, e);
            if (topLevel) {
                LOGGER.log(Level.WARNING, "Failed to convert node tree to a "
                        + type.getSimpleName()
                        + " object without modifications: " + originalTree, e);
                LOGGER.log(Level.INFO,
                        "Modified node tree was successfully converted to a "
                                + type.getSimpleName() + " object: " + tree);
            }
        } catch (JsonProcessingException e) {
            throw new YourException("Failed to convert node tree to a "
                    + type.getSimpleName() + " object: " + tree, e);
        }

        return object;
    }

    private static <T> T toTypedObject(Class<T> type, JsonNode tree,
            String originalTree,
            MismatchedInputException mismatchedInputException) {

        T object;

        List<Reference> path = mismatchedInputException.getPath();
        if (path != null && !path.isEmpty()) {

            try {

                ObjectNode subNode = (ObjectNode) tree;
                for (int i = 0; i < path.size(); i++) {
                    String fieldName = path.get(i).getFieldName();
                    if (i + 1 < path.size()) {
                        subNode = (ObjectNode) tree.get(fieldName);
                    } else {
                        subNode.remove(fieldName);
                    }
                }
                object = toTypedObject(type, tree, false);

            } catch (Exception e) {
                throw new YourException("Failed to convert node tree to a "
                        + type.getSimpleName() + " object: " + originalTree,
                        mismatchedInputException);
            }

        } else {
            throw new YourException(
                    "Failed to convert node tree to a " + type.getSimpleName()
                            + " object: " + originalTree,
                    mismatchedInputException);
        }

        return object;
    }

}

Звоните с:

YourObject yourObject = YourClass.toTypedObject(YourObject.class, tree);

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