Почему я могу полностью неправильно указывать теги классов десериализации в xml-файле с помощью Jackson?

#java #jackson #deserialization

#java #джексон #десериализация

Вопрос:

Я использую Jackson для десериализации XML-файла:

 public SomeClassDTO deserializeXML(String pathToFile) {
    File file = new File(pathToFile);
    XmlMapper xmlMapper = new XmlMapper();
    String xml = null;
    try {
        xml = inputStreamToString(new FileInputStream(file));
        xml = xml.replaceAll("\s ","");
    } catch (FileNotFoundException fileNotFoundException) {
        logger.error("file could not be found");
    }
    SomeClassDTO value = new SomeClassDTO();
    try {
        value = xmlMapper.readValue(xml, SomeClassDTO.class);
    } catch (JsonProcessingException jsonProcessingException) {
        logger.error("Deserialization failed");
        jsonProcessingException.printStackTrace();
    }
    return value;
}

public String inputStreamToString(InputStream is) {
    StringBuilder sb = new StringBuilder();
    String line;

    try (BufferedReader br = new BufferedReader(new InputStreamReader(is))) {
        while ((line = br.readLine()) != null) {
            sb.append(line);
        }
    } catch (IOException ioException) {
        logger.error("Die Konfigurationsdatei kann nicht gelesen werden.");
        ioException.printStackTrace();
    }
    return sb.toString();
}
 

Кроме того, вот как выглядит SomeClassDTO следующим образом:

 import java.util.ArrayList;
import java.util.List;

public class SomeClassDTO {
    private List<Book> books = new ArrayList<>();

    public List<Book> getBooks() {
        return books;
    }

    public void setBooks(List<Book> books) {
        this.books = books;
    }
}
 

А вот как выглядит Книжный класс:

 class Book {
private String name;

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}
 

}

И это XML-файл, который я пытаюсь прочитать:

 <SomeClassDTO>
<books>
    <Boosdfsk>
        <name>sldjfks</name>
    </Boosdfsk>
    <Book>
        <name>blablub</name>
    </Book>
</books>
</SomeClassDTO>
 

Как вы можете видеть, совершенно необязательно, если я напишу «Book» или «Booksdhfsj» или что-то еще.
Этот факт действительно сбивает меня с толку.

Комментарии:

1. Насколько я знаю, существует конфигурация / свойство с именем «deserialization-fail-on-unknown-properties» или что-то подобное, которое по умолчанию равно false, что означает, что если во время десериализации оно встречает свойство, которое оно не может сопоставить (например, Boosdfsk), оно просто проигнорирует их, а не выдаст ошибку. Таким образом, результат вашей десериализации должен быть таким же, как если бы вы удалили неправильный <Boosdfsk> тег.

2. Если я нашел фрагмент кода xmlMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true); , к сожалению, он все еще не работает.

Ответ №1:

Поскольку Jackson имеет достаточно информации о десериализованном типе путем проверки books свойства, ему не нужно ничего знать о теге, используемом для каждого дочернего объекта. Он знает, что каждый дочерний элемент будет a Book .

Вы можете увидеть соответствующий разговор в этом выпуске GitHub: https://github.com/FasterXML/jackson-dataformat-xml/issues/322

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

Если вы хотите читать только Book s, одним из вариантов было бы создать класс Books , который считывает список книг как развернутый список.