Další anotace v JAXB

V jednom z předchozích příspěvků jsem se věnoval základní práci s JAXB, kde jsem používal pouze dvě anotace a to @XmlRootElement a @XmlType. Podívejme se na část vytvořeného xml souboru.

<company>
    <centers>
        <code>METPRG</code>
        <description>Office center Metronom in Prague</description>
        <rooms>
            <code>A02</code>
            <numberOfSeats>14</numberOfSeats>
        </rooms>
        <rooms>
            <code>A13</code>
            <numberOfSeats>42</numberOfSeats>
        </rooms>
        <rooms>
            <code>B08</code>
            <numberOfSeats>22</numberOfSeats>
        </rooms>
    </centers>
    <centers>
        <code>AVIPRG</code>
        <description>Office center Aviatica in Prague</description>
        <rooms>
            <code>AA41</code>
            <numberOfSeats>70</numberOfSeats>
        </rooms>
        <rooms>
            <code>CA12</code>
            <numberOfSeats>38</numberOfSeats>
        </rooms>
        ...

Company obsahuje seznam elementů center a ty v sobě mají seznam elementů room. Když se podíváte pečlivěji, uvidíte, že každý element center se jmenuje centers a každý element room se jmenuje rooms. Určitě by to lépe vypadalo, kdyby se tyto elementy jmenovaly center a room. Nebo možná ještě lépe, kdyby se element center jmenoval jednoznačněji business_center. Jak center tak room obsahují element code. Bylo čitelnější, kdyby se jmenovaly center_code a room_code. A také kořenový element company by mohl obsahovat ještě atribut s názvem společnosti. To vše je možné, když použijeme další anotace, které JAXB nabízí.

Anotace @XmlAccessorType říká, že každý field (nestatická a netransientní proměnná – to jsou v tomto příkladu všechny) bude svázán s xml elementem.
Anotaci @XmlElementWrapper použijeme, když pracujeme se seznamem. Vytvoříme element, který bude v sobě obsahovat jednotlivé elementy seznamu.
Anotace @XmlAttribute nevytvoří xml element, ale atribut. Pomocí hodnoty, kterou přiřadíme do name nastavíme atributu název.
Když použijeme anotaci @XmlElement, můžeme předat hodnotu name a tím nastavíme názvem xml elementu.

Jasnější to bude na příkladu.

App.java

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;

public class App {

	public static void main(String[] args) throws JAXBException {

		// marshal
		JAXBContext context = JAXBContext.newInstance(Company.class);
		Marshaller marshaller = context.createMarshaller();
		marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
		File file = new File("company.xml");
		// writes to file
		marshaller.marshal(createCompany(), file);
		// writes to System.out
		marshaller.marshal(createCompany(), System.out);
		
		// unmarshal
		Unmarshaller unmarshaller = context.createUnmarshaller();
		Company company = (Company)unmarshaller.unmarshal(file);
		// print unmashalled object
		System.out.println();
		for (Center center : company.getCenters()) {
			System.out.println(center.getCode() + " - " + center.getDescription());
			for (Room room : center.getRooms()) {
				System.out.println("room: " + room.getCode() + "\t number of seats: " + room.getNumberOfSeats());
			}
			System.out.println();
		}
	}

	private static Company createCompany() {
		Center metronomPrague = new Center();
		metronomPrague.setCode("METPRG");
		metronomPrague.setDescription("Office center Metronom in Prague");
		metronomPrague.setRooms(
				Arrays.asList(
						new Room("A02", 14), 
						new Room("A13", 42), 
						new Room("B08", 22)));

		Center aviaticaPrague = new Center();
		aviaticaPrague.setCode("AVIPRG");
		aviaticaPrague.setDescription("Office center Aviatica in Prague");
		aviaticaPrague.setRooms(
				Arrays.asList(
						new Room("AA41", 70), 
						new Room("CA12", 38), 
						new Room("CA18", 24),
						new Room("CB52", 88), 
						new Room("CD11", 62)));

		Company company = new Company();
		company.setName("1. Nájemní, s.r.o.");
		company.setCenters(new ArrayList<>());
		company.getCenters().add(metronomPrague);
		company.getCenters().add(aviaticaPrague);

		return company;
	}
}

Company.java

import java.util.List;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Company {

	@XmlAttribute(name = "company_name")
	private String name;

	@XmlElement(name = "business_center")
	@XmlElementWrapper(name = "business_centers")
	private List<Center> centers;

	// getters and setters
}

Oproti kódu z předchozího příspěvku jsem přidal field private String name a označil jej anotací @XmlAttribute(name = „company_name“), která vytvoří xml atribut s názvem company_name. V App.java přiřazujeme do proměnné name hodnotu „1. Nájemní, s.r.o“ takže v xml souboru to bude vypadat následovně:

<company company_name="1. Nájemní, s.r.o.">
...
</company>

Anotace @XmlElementWrapper(name = „business_centers“) vytvoří xml element business_center a v něm budou obsaženy jako elementy všechny objekty ze seznamu. Anotace @XmlElement(name = „business_center“) nastaví název každého elementu v listu na business_center.

<business_centers>
    <business_center>
        ...
    </business_center>
    <business_center>
        ...
    </business_center>
</business_centers>

Center.java

import java.util.List;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlType;

@XmlType
@XmlAccessorType(XmlAccessType.FIELD)
public class Center {

	@XmlElement(name = "center_code")
	private String code;
	@XmlElement(name = "center_description")
	private String description;
	@XmlElementWrapper(name = "rooms")
	@XmlElement(name = "room")
	private List<Room> rooms;
	
	// getters and setters
}

Anotace @XmlElement(name = „center_code“) nastaví xml elementu název center_code. Stejné je to pro @XmlElement(name = „center_description“).

<center_code>METPRG</center_code>
<center_description>Office center Metronom in Prague</center_description>

Anotace @XmlElementWrapper(name = „rooms“) a @XmlElement(name = „room“) jsou obdobné jako ty, co jsme si vysvětlili na třídě Company.

Room.java

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;

@XmlType
@XmlAccessorType(XmlAccessType.FIELD)
public class Room {

	@XmlElement(name = "room_code")
	private String code;
	private int numberOfSeats;
	
	public Room() {}
	
	// setters and getters
}

V této třídě již není nic nového. Výsledný soubor vypadá následovně.

Company.xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<company company_name="1. Nájemní, s.r.o.">
    <business_centers>
        <business_center>
            <center_code>METPRG</center_code>
            <center_description>Office center Metronom in Prague</center_description>
            <rooms>
                <room>
                    <room_code>A02</room_code>
                    <numberOfSeats>14</numberOfSeats>
                </room>
                <room>
                    <room_code>A13</room_code>
                    <numberOfSeats>42</numberOfSeats>
                </room>
                <room>
                    <room_code>B08</room_code>
                    <numberOfSeats>22</numberOfSeats>
                </room>
            </rooms>
        </business_center>
        <business_center>
            <center_code>AVIPRG</center_code>
            <center_description>Office center Aviatica in Prague</center_description>
            <rooms>
                <room>
                    <room_code>AA41</room_code>
                    <numberOfSeats>70</numberOfSeats>
                </room>
                <room>
                    <room_code>CA12</room_code>
                    <numberOfSeats>38</numberOfSeats>
                </room>
                <room>
                    <room_code>CA18</room_code>
                    <numberOfSeats>24</numberOfSeats>
                </room>
                <room>
                    <room_code>CB52</room_code>
                    <numberOfSeats>88</numberOfSeats>
                </room>
                <room>
                    <room_code>CD11</room_code>
                    <numberOfSeats>62</numberOfSeats>
                </room>
            </rooms>
        </business_center>
    </business_centers>
</company>

Napsat komentář