1. Обзор
В этом руководстве мы увидим, как преобразовать XML-сообщение в JSON с помощью Jackson.
Читателям, плохо знакомым с Джексоном, рекомендуется сначала ознакомиться с основами .
2. Знакомство с Джексоном
С Джексоном мы можем думать о парсинге JSON тремя разными способами:
- Первый и самый распространенный — привязка данных с помощью
ObjectMapper.
- Второй — сопоставление с древовидной структурой данных с помощью
TreeTraversingParser
иJsonNode.
- И третий — стримить древовидную структуру данных по токену, используя
JsonParser
иJsonGenerator.
Теперь Джексон также поддерживает первые два для данных XML. Таким образом, давайте посмотрим, как Джексон может помочь нам преобразовать один формат в другой.
3. Зависимости
Во- первых, нам нужно добавить зависимость jackson -databind
в наш pom.xml
:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.13.0</version>
</dependency>
Эта библиотека позволит нам использовать API привязки данных.
Второй — jackson-dataformat-xml
, который добавляет поддержку XML Джексона:
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
<version>2.13.0</version>
</dependency>
4. Привязка данных
Проще говоря, привязка данных — это когда мы хотим отобразить сериализованные данные непосредственно в объект Java.
Чтобы изучить это, давайте определим наш XML со свойствами Flower
и Color
:
<Flower>
<name>Poppy</name>
<color>RED</color>
<petals>9</petals>
</Flower>
Это похоже на эту нотацию Java:
public class Flower {
private String name;
private Color color;
private Integer petals;
// getters and setters
}
public enum Color { PINK, BLUE, YELLOW, RED; }
Нашим первым шагом будет преобразование XML в экземпляр Flower
. Для этого давайте создадим экземпляр XmlMapper
, XML-эквивалент Джексона для ObjectMapper
, и воспользуемся его методом readValue
:
XmlMapper xmlMapper = new XmlMapper();
Flower poppy = xmlMapper.readValue(xml, Flower.class);
Как только у нас будет наш экземпляр Flower
, мы захотим записать его как JSON, используя знакомый ObjectMapper
:
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(poppy);
И, в результате, мы получаем наш JSON-эквивалент:
{
"name":"Poppy",
"color":"RED",
"petals":9
}
5. Обход дерева
Иногда просмотр непосредственно древовидной структуры может обеспечить большую гибкость, например, в случае, когда мы не хотим поддерживать промежуточный класс или хотим преобразовать только часть структуры.
Хотя, как мы увидим, это сопряжено с некоторыми компромиссами.
Первый шаг аналогичен нашему первому шагу, когда мы используем привязку данных. Однако на этот раз мы будем использовать метод readTree
:
XmlMapper xmlMapper = new XmlMapper();
JsonNode node = xmlMapper.readTree(xml.getBytes());
Сделав это, мы получим JsonNode
, у которого, как мы и ожидали, 3 дочерних элемента: имя, цвет
и лепестки
.
Затем мы снова можем использовать ObjectMapper
, просто отправив вместо этого наш JsonNode
:
ObjectMapper jsonMapper = new ObjectMapper();
String json = jsonMapper.writeValueAsString(node);
Теперь результат немного отличается от нашего последнего примера:
{
"name":"Poppy",
"color":"RED",
"petals":"9"
}
При внимательном рассмотрении мы видим, что атрибут лепестков сериализуется в строку, а не в число! Это связано с тем, что readTree
не выводит тип данных без явного определения.
5.1. Ограничения
Кроме того, существуют определенные ограничения поддержки обхода XML-дерева Джексона:
- Джексон не может отличить объект от массива. Поскольку в XML отсутствуют собственные структуры, позволяющие отличить объект от списка объектов, Джексон просто сопоставит повторяющиеся элементы в одно значение.
- А поскольку Джексон хочет сопоставить каждый элемент XML с узлом JSON, он не поддерживает смешанный контент.
По этим причинам официальная документация Джексона не рекомендует использовать древовидные модели для разбора XML .
6. Ограничения памяти
Теперь у обоих есть заметный недостаток, заключающийся в том, что весь XML должен быть в памяти сразу, чтобы выполнить преобразование. Пока Джексон не поддерживает потоковую передачу древовидной структуры в виде токенов, мы застрянем на этом ограничении или нам нужно будет взглянуть на создание собственной структуры с помощью чего-то вроде XMLStreamReader .
7. Заключение
В этом руководстве мы кратко изучили различные способы, которыми Джексон может читать XML-данные и записывать их в JSON. Кроме того, мы кратко рассмотрели ограничения каждого поддерживаемого подхода.
Как обычно, полный исходный код, сопровождающий руководство, доступен на GitHub .