— Не так швидко, юначе! У мене тобі ще дві лекції!
— Дві? Ого. Ну добре. Чого не зробиш заради власної крутості. Я готовий слухати.
— XML, як і JSON, часто застосовується при пересиланні даних між різними програмами та комп'ютерами. І так само є кілька фреймворків, які значно полегшують життя Java-програмістів при роботі з XML. Сьогодні я познайомлю тебе з одним із них.
JAXB – це чудовий багатофункціональний фреймворк для роботи з XML.
JAXB – це частина JDK, тому завантажувати його окремо не потрібно.
Давай я спочатку покажу тобі приклад роботи з ним, а потім ми його розберемо. Приклад:
< code>
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< /span>); //перетворюємо у рядок все записане в StringWriter String result = writer.toString(); System.out.println(result); }
@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:
public static void main(String[] args) throws JAXBException { String xmldata = "<cat> <name>Murka</name><age>5</age>< /span><weight>4</weight></cat>""; StringReader reader = новий StringReader(xmldata); JAXBContext context = JAXBContext.newInstance(Cat.class); Unmarshaller unmarshaller = context.createUnmarshaller(); Cat cat = (Cat) unmarshaller. unmarshal(reader); }
@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 замість полів.
Обіцяний приклад:
public static void main(String[] args) throws JAXBException { //створення об'єктів Cat&Zoo для серіалізації в XML Cat cat = новий Cat(); cat.name = "Murka"; cat.age = 5; cat.weight = 4; Zoo zoo = новий 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()); }
@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>< /pre>Зверніть увагу: цього разу ми серіалізуємо не об'єкт Cat, а об'єкт типу Zoo, яких зберігає колекцію об'єктів Cat.
Об'єкт cat в колекцію був доданий двічі, тому він двічі в XML .
У колекції є свій тег – «wild-animals» , який обрамляє всі елементи колекції.
Елементи age & weight стали атрибутамиage & w.
За допомогою атрибуту @XmlElement ми змінили тег cat на tiger.
Зверни ще увагу на рядок 17, тепер ми передаємо в JAXB-контекст два класи - Zoo & Cat, т.к. вони обидва беруть участь у серіалізації.
— Сьогодні дуже цікавий день – стільки нового.
— Ага. Радий за тебе. Зараз зробимо невелику перерву і продовжимо.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ