На этом шаге мы рассмотрим сериализацию сложных объектов
Ранее мы привели примеры для сериализации и десериализации объектов, которые содержат поля примитивных типов. В случае, когда класс содержит поля, которые сами по себе является объектами, например, списками, то сериализация происходит немного по-другому. Обратимся к следующему примеру.
import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement(name = "cat") @XmlAccessorType(XmlAccessType.FIELD) public class Cat { // 1 @XmlAttribute private String name; @XmlAttribute private int age; public Cat() { } public Cat(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
import javax.xml.bind.annotation.*; import java.util.ArrayList; import java.util.List; @XmlRootElement(name = "Zoo") @XmlAccessorType(XmlAccessType.FIELD) public class Zoo { // 1 @XmlElement(name = "cat") // 2 @XmlElementWrapper private List<Cat> pets = new ArrayList<>(); public Zoo() { } public List<Cat> getPets() { return pets; } public void setPets(List<Cat> pets) { this.pets = pets; } public void addCat(Cat cat) { pets.add(cat); } }
import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import java.io.File; public class Main { public static void main(String[] args) throws JAXBException { Zoo zoo = makeZoo(); File outFile = new File("cats.xml"); // 1 Marshaller marshaller = getMarshaller(Zoo.class, Cat.class); marshaller.marshal(zoo, outFile); System.out.println("сериализация завершена"); } /** * Функция для создания объекта Zoo * * @return объект zoo */ private static Zoo makeZoo() { Zoo zoo = new Zoo(); zoo.addCat(new Cat("Boris", 10)); zoo.addCat(new Cat("Tom", 5)); return zoo; } /** * Функция для создания Marshaller. * * @param classes Список классов, которые участвуют в сериализации * @return Marshaller */ private static Marshaller getMarshaller(Class... classes) throws JAXBException { JAXBContext context = JAXBContext.newInstance(classes); Marshaller marshaller = context.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); return marshaller; } }
Проект можно взять здесь
Рис. 1. Результат работы программы
Поговорим о нем поподробнее. Начнем с файла Cat.java. В пункте 1 мы говорим, что данное поле будет являться атрибутом тега, а не внутренним тегом будущего тега cat (его мы указали с помощью аннотации @XmlRootElement). Имя атрибута по умолчанию совпадает с именем поля. Если вы хотите сменить имя атрибута, то воспользуйтесь следующей записью:
@XmlAttribute(name = "НОВОЕ_ИМЯ")
Рассмотрим теперь файл Zoo.java. В данном классе полем является список домашних животных (котов). Если не указать пункт 1 и пункт 2, то имя тега каждого элемента будет называться pets. Поэтому в пункте 1 мы указываем, что каждый тег будет иметь имя cat. Более того, в пункте 2 мы указали, что все теги cat будут обернуты тегом pets (рисунок 1).
И, наконец, рассмотрим файл Main.java. Для сериализации полей, не являющимися примитивными типами, нужно указывать контексту JAXB их участие в сериализации. Это мы сделали в пункте 1.
На следующем шаге мы рассмотрим десериализацию сложных объектов