JAXB

Java Collections
3 уровень , 7 лекция
Открыта

— Не так быстро, молодой человек! У меня для тебя еще две лекции!

— Две? Ого. Ну, ладно. Чего ни сделаешь ради собственной крутости. Я готов слушать.

— XML, как и JSON, часто применяется при пересылке данных между разными программами и компьютерами. И так же есть несколько фреймворков, которые значительно упрощают жизнь Java-программистов при работе с XML. Сегодня я познакомлю тебя с одним из них.

JAXB – это отличный многофункциональный фреймворк для работы с XML.

JAXB - 1

JAXB – это часть JDK, поэтому скачивать его отдельно не требуется.

Давай я сначала покажу тебе пример работы с ним, а после мы его разберем. Пример:

Конвертация объекта в XML

public static void main(String[] args) throws JAXBException { //создание объекта для сериализации в XML Cat cat = new Cat(); cat.name = "Murka"; cat.age = 5; cat.weight = 4; //писать результат сериализации будем в Writer(StringWriter) StringWriter writer = new StringWriter(); //создание объекта Marshaller, который выполняет сериализацию JAXBContext context = JAXBContext.newInstance(Cat.class); Marshaller marshaller = context.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); // сама сериализация marshaller.marshal(cat, writer); //преобразовываем в строку все записанное в StringWriter String result = writer.toString(); System.out.println(result); }
Класс, объект которого конвертирует в XML
@XmlType(name = "cat") @XmlRootElement public class Cat { public String name; public int age; public int weight; public Cat() { } }
Результат сериализации и вывода на экран:
<cat>
<name>Murka</name>
<age>5</age>
<weight>4</weight>
</cat>

— Что-то мне этот код один в один напоминает сериализацию в JSON. Тоже аннотации, но там был ObjectMapper, тут Context & Marshaller.

— Ага. Действительно они очень похожи. Jackson писался по образцу JAXB. Но и JAXB то же с кого-то списали. Нельзя выдумать нечто гениальное на пустом месте.

— Похоже на то.

— Ок, вот что там происходит:

В строках 5-8 мы создаем объект класса Cat и заполняем его данными.

Строка 11 – создаем объект Writer для записи результата.

Стока 14 – создаем «контекст». Это аналог ObjectMapper, но от него потом создаются еще два дочерних объекта Marshaller – для сериализации, и Unmarshaller для десериализации. Небольшие отличия от Jackson, но – непринципиально.

Строка 15 – создаем объект Marshaller. Маршалинг – это синоним слова сериализация.

Строка 16 – устанавливает свойство FORMATTED_OUTPUT в TRUE. В результат будут добавлены переносы строки и пробелы, чтобы код был читабельным для человека, а не весь текст в одну строку.

Строка 18 – сериализация объекта.

Строки 21-22 – вывод результата сериализации на экран.

— А что это еще за аннотации @XmlType(name = «cat») и @XmlRootElement?

— @XmlRootElement указывает на то, что этот объект может быть «корнем дерева» элементов в XML. Т.е. быть элементом самого верхнего уровня, все остальные элементы лежат в нем.

@XmlType(name = «cat») указывает на то, что класс участвует в JAXB сериализации, в ней же задано имя, которое будет у XML-тега для этого класса.

Ладно, давай теперь покажу пример десериализации из XML:

Конвертация объекта из XML
public static void main(String[] args) throws JAXBException
{
 String xmldata = "<cat><name>Murka</name><age>5</age><weight>4</weight></cat>"";
 StringReader reader = new StringReader(xmldata);

 JAXBContext context = JAXBContext.newInstance(Cat.class);
 Unmarshaller unmarshaller = context.createUnmarshaller();

 Cat cat = (Cat) unmarshaller.unmarshal(reader);
}
Класс, объект которого десериализуется из XML
@XmlType(name = "cat") @XmlRootElement public class Cat { public String name; public int age; public int weight; public Cat() { } }

Все практически аналогично случаю с Jackson. Но на всякий случай объясню все, что тут происходит.

Строка 3 – задаем строку, которая хранит xml для десериализации.

Строка 4 – оборачиваем xml-строку в StringReader.

Строка 6 – создаем JAXB-контекст, куда передаем список классов.

Строка 7 — создаем Unmarshaller – объект, который будет выполнять десериализацию.

Строка 9 – десериализуем xml из объекта reader и получаем объект cat типа Cat.

— Теперь это все выглядит чуть ли не очевидно. А еще пару часов назад, я ломал голову — как же это работает.

— Так всегда бывает, когда становишься умнее – сложные вещи становятся простыми.

— Я становлюсь умнее? Это не может не радовать.

— Отлично. Тогда вот тебе список аннотаций, которые ты можешь использовать, чтобы управлять результатом JAXB сериализации:

JAXB-аннотации Описание
@XmlElement(name) Ставится около поля.
Поле будет представлено в XML-элементом.
Позволяет задать имя для тэга.
@XmlAttribute(name) Ставится около поля.
Поле будет представлено в XML-атрибутом!
Позволяет задать имя для атрибута.
@XmlElementWrapper(nillable = true) Ставится около поля.
Позволяет задать «обрамляющий тег» для группы элементов.
@XmlType Ставится около класса.
Позволяет задать метод для создания объекта, если конструктор по умолчанию private.
@XmlJavaTypeAdapter Ставится около поля.
Позволяет задать класс, который будет преобразовывать данные поля в строку.

— Как интересно. А можно примеры с этими аннотациями, а то написанное – это одно, а живой пример – это совсем другое.

— Ок. Будет тебе пример. Хотел только добавить, то JAXB позволяет ставить аннотации у методов getter/setter вместо полей.

Обещанный пример:

Конвертация объекта в XML
public static void main(String[] args) throws JAXBException
{
 //создание объектов Cat&Zoo для сериализации в XML
 Cat cat = new Cat();
 cat.name = "Murka";
 cat.age = 5;
 cat.weight = 4;

 Zoo zoo = new Zoo();
 zoo.animals.add(cat);
 zoo.animals.add(cat);

 //писать результат сериализации будем во Writer(StringWriter)
 StringWriter writer = new StringWriter();

 //создание объекта Marshaller, который выполняет сериализацию
 JAXBContext context = JAXBContext.newInstance(Cat.class, Zoo.class);
 Marshaller marshaller = context.createMarshaller();
 marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
 // самосериализация
 marshaller.marshal(zoo, writer);

 //преобразовываем все записанное в StringWriter в строку
 System.out.println(writer.toString());
}
Класс, объект которого конвертирует в XML
@XmlType(name = "zoo") @XmlRootElement public class Zoo { @XmlElementWrapper(name="wild-animals", nillable = true) @XmlElement(name = "tiger") public List 
   
     animals = new ArrayList<>(); } 
   

public class Cat {
 @XmlElement(name = "catname")
 public String name;
 @XmlAttribute(name = "age")
 public int age;
 @XmlAttribute(name = "w")
 public int weight;

 public Cat() { } }
Результат сериализации и вывода на экран:
<zoo>
<wild-animals>
<tiger age="5" w="4">
<catname>Murka</catname>
</tiger>
<tiger age="5" w="4">
<catname>Murka</catname>
</tiger>
</wild-animals>
</zoo>

Обрати внимание: в этот раз мы сериализуем не объект Cat, а объект типа Zoo, которых хранит коллекцию объектов Cat.

Объект cat в коллекцию был добавлен дважды, поэтому он 2 раза в XML.

У коллекции есть свой тег – «wild-animals» , который обрамляет все элементы коллекции.

Элементы age & weight стали атрибутами age & w.

С помощью атрибута @XmlElement мы поменяли тэг cat на tiger.

Обрати еще внимание на строку 17, теперь мы передаем в JAXB-контекст два класса – ZooCat, т.к. они оба участвуют в сериализации.

— Сегодня очень интересный день – столько нового.

— Ага. Рад за тебя. Сейчас сделаем небольшой перерыв и продолжим.

Комментарии (102)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Juki Уровень 51
13 октября 2023
сначала прочитала "чего не сделаешь ради собственной ГРУСТНОСТИ... " 😢
Anonymous #3177672 Уровень 51
29 июля 2023
Поделюсь своим маленьким "открытием". Вместе с IntelliJ IDEA поставляются часто используемые библиотеки для JAVA (возможно, еще и для котлина). Они находятся в папке, куда установлена IDE, в директории LIB. Перед тем, как гуглить нужную библиотеку, советую покопаться там.
Daniel Уровень 51
18 апреля 2023
У меня получилось завести шарманку вот с таким набором javax.xml.bind:jaxb-api:2.3.1 javax.activation:activation:1.1.1 org.glassfish.jaxb:jaxb-runtime:2.3.3 com.sun.istack » istack-commons-runtime:3.0.10
Антон Уровень 50
30 октября 2023
Подтверждаю, что указанное сочетание работает. Грузим: File->Project Structure->Libraries->from Maven Каждый из элементов грузится отдельно. Не знаю важно или нет: Там с каждым подгружается по целому пакету классов и получается дублирование. Лишние удалял.
TemaCode Уровень 51
7 февраля 2023
JAXB – это часть JDK, поэтому скачивать его отдельно не требуется (c.) --- это как?
VladimirPic Уровень 38
19 февраля 2023
milniy87 Уровень 41
20 марта 2023
Странно, но мне не нужно устанавливать библиотеки. она вшита в ide
safelogj Уровень 51
27 сентября 2024
JAXB (Java Architecture for XML Binding) была частью JDK до версии 11. Начиная с JDK 11, JAXB была вынесена в отдельный модуль и больше не включается в стандартный JDK. Теперь для работы с JAXB необходимо добавлять соответствующую зависимость, например, через Maven или Gradle. gpt
Ясин Адли Уровень 24
27 января 2023
почему лекции после базового курса для платных акков закрыты? уважаемая администрация, вот я щас изучаю данную библиотеку, чтобы ее открыть мне нужна мана, а маны не хватает, я не хочу все подряд проходить до этой лекции, ну откройте вы хоть лекции, черт с ними с примерами
artur К Уровень 47
1 марта 2023
Открой урок в браузере через инкогнито режим
Эдуард Уровень 17
16 декабря 2022
Кстати, а почему в примере нет extends Animals у Cat?
Galina K. Уровень 39
21 декабря 2022
Вроде в примерах нет класса Animals, есть только коллекция animals в классе Zoo (в нее добавляют об'екты Cat)
Barm Уровень 38
7 сентября 2022
Для 17 java <dependency> <groupId>jakarta.xml.bind</groupId> <artifactId>jakarta.xml.bind-api</artifactId> <version>4.0.0</version> </dependency> <dependency> <groupId>com.sun.xml.bind</groupId> <artifactId>jaxb-impl</artifactId> <version>4.0.0</version> <scope>runtime</scope> </dependency>
Бостон Уровень 26
5 июня 2022
Лишние закрывающие кавычки в десериализации: String xmldata = "<cat><name>Murka</name><age>5</age><weight>4</weight></cat>"";