undefined

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
class Cat
{
 public String name;
 public int age;
 public int weight;

 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
class Cat
{
 public String name;
 public int age;
 public int weight;

 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 = newStringWriter();

 //создание объекта 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
class Zoo
{
 @XmlElementWrapper(name="wild-animals", nillable = true)
 public List animals = new ArrayList
}

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

 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.

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

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

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

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

Комментарии (59)
Чтобы просмотреть все комментарии или оставить свой,
перейдите в полную версию
Иван Сибиряков 35 уровень, Санкт-Петербург
20 апреля 2021
Галопом по Европам, что называется. Каждая лекция - какая-то новая и весьма обширная тема, которая практически никак толком не раскрывается, а только пугает и заставляет чувствовать себя тупым. Вообще это уже в многопоточности было, но я только сейчас осознал, что курс перестал быть самодостаточным от слова совсем. Комментарии с полезными ссылками спасают. Открыл для себя несколько хороших сайтов. Приходится после каждой лекции углубляться в поднятые этой же лекцией темы.
DZ 35 уровень
9 декабря 2020
Чем больше я узнаю, тем больше понимаю, что ничего не знаю
Татьяна 41 уровень, Днепр
25 ноября 2020
Сами задачи элементарные, но запустить никак не получалось. Через майвен искала и подключала вот такие 3: javax.xml.bind:jaxb-api:2.3.0 javax.activation:activation:1.1 org.glassfish.jaxb:jaxb-runtime:2.3.0 Потом скачала и установила jdk8 и переключилась на нее таким образом: Project Structure → Project Settings → Project → Project SDK Project Structure → Project Settings → Project → Project language level и выбрать подходящий под проект уровень. После этого все заработало. Возможно, помогло бы просто переключиться на java8 без мавенов... Может кому пригодиться )
ram0973 41 уровень, Набережные Челны
29 июля 2020
комменты, которые открываются вверх, без сохранения текущего места - это не гуд
RexyComandante 41 уровень, Минск
7 июля 2020
Если у вас Intellij IDEA, то необходимый библиотеки есть в комплекте (кстати, как и в случае с Jackson). Найти их можно по следующему адресу: папка с IDEA -> lib В данном случае нужны: 1. jaxb-api 2. jaxb-runtime 3. javax.activation
Edffom 33 уровень, Мирный
20 апреля 2020
Хотел затестить первый пример, импортнул jaxb-api-2.3.1.jar но не помогло - Exception in thread "main" javax.xml.bind.JAXBException: Implementation of JAXB-API has not been found on module path or classpath. - with linked exception: и куча гневных сообщений
Дмитрий Дмитрий 35 уровень, Новосибирск
11 апреля 2020
Кто нибудь просто тестил приведенные примеры аннотаций?

@XmlElementWrapper(nillable = true)	Ставится около поля.
НЕ просто поля! Если просто поля, то крашиться со словами: @XmlElementWrapper is only allowed on a collection property but "TestJAXB.JAXB$Dog1.name" is not a collection property.
@XmlType(name = «cat») в ней же задано имя, которое будет у XML-тега для этого класса.
Вы пробовали поменять имя? Ничего не происходит! Имя как ставилось по дефолту именем класса в нижнем регистре, так и ставиться!
Валентин Кудинов 41 уровень, Самара
15 марта 2020
Т.к. для настройки сериализации используются аннотации а знаний про них у меня в голове мало решил подтянуть. Для тех кто хочет больше понимания что такое аннотации как их создавать и как использовать видео про аннотации и рефлексию Здесь первое видео аннотации второе про рефлексию. После просмотра стал чувствовать себя увереннее при упоминании данных терминов. Также отличное видео этого же автора Юрия Ткач про сериализацию JSON фреймворком от гугл Для использования нужно всего лишь две строчки кода и никаких аннотаций! Очень круто.
vinograd 33 уровень
18 февраля 2020
JXAB MVNRepository ссылка для скачивания библиотки jar или прямая ссылка Добавление в ваш проект: File->Project Structure Modules->Dependencies потом клацаем полюсик и добавляем скачанный файл
CTAPuk 41 уровень, Москва
12 января 2020
Есть опечатки, а также несоответствия и похоже неслучайные, потому что - это "Путь" :)