JAXB jednoduše

JAXB (Java Architecture for XML Bindings) je Java standard, který určuje, jak mají být Java objekty převedeny do a z xml. JAXB představuje rozhraní pro čtení a zápis Java objektů do a z xml. Pro zápis Java objektů do xml se používá metoda marshall() a pro načtění z xml do Java objektů metoda unmarshall(). JAXB používá anotace pro mapování Java objektů na xml elementy a zpět. Dvě nejpoužívanější anotace jsou @XmlRootElement (xml dokument musí mít root element a tato anotace označuje třídu, která v xml bude představovat root element) a @XmlType (označuje xml element).

V příkladu si ukážeme fiktivní firmu (Company), která pronajímá kanceláře (Room) v různých office centrech (Center).

Nejdříve si vytvoříme třídu Room, která bude představovat místnost v office centru k pronájmu. Zároveň tuto třídu namapujeme na element room. Namapováním je myšleno to, že řekneme, že naše třída má být v xml dokumentu reprezentována elementem room. To provedem tak, že ji označíme anotací @XmlType.

Room.java

import javax.xml.bind.annotation.XmlType;

@XmlType
public class Room {

	private String code;
	private int numberOfSeats;
	
	// musí mít defaultní konstruktor
	public Room() {}
	
	public Room(String code, int numberOfSeats) {
		this.code = code;
		this.numberOfSeats = numberOfSeats;
	}

	public String getCode() {
		return code;
	}
	
	public void setCode(String code) {
		this.code = code;
	}

	public int getNumberOfSeats() {
		return numberOfSeats;
	}

	public void setNumberOfSeats(int numberOfSeats) {
		this.numberOfSeats = numberOfSeats;
	}
}

Všimněte si, že třída Room má dva konstruktory. Proto, aby JAXB fungovalo, je nutné, aby objekty mapované na elementy měly bezparametrický konstruktor.

Obdobně to provedeme s třídou Center, která představuje obchodní centrum, ve kterém jsou jednotlivé místonosti k pronájmu (Room).

Center.java

import java.util.List;

import javax.xml.bind.annotation.XmlType;

@XmlType
public class Center {

	private String code;
	private String description;
	private List<Room> rooms;
	
	public String getCode() {
		return code;
	}

	public void setCode(String code) {
		this.code = code;
	}

	public String getDescription() {
		return description;
	}

	public void setDescription(String description) {
		this.description = description;
	}

	public List<Room> getRooms() {
		return rooms;
	}

	public void setRooms(List<Room> rooms) {
		this.rooms = rooms;
	}
}

Nyní vytvoříme třídu Company, která bude namapována na xml element company. Bude se jednat o root element. Tento element představuje celou naši firmu. To, že třída má být namapována na root element, řekneme tak, že ji označíme anotací @XmlRootElement.

Company.java

import java.util.ArrayList;
import java.util.List;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Company {

	private List<Center> centers;

	public List<Center> getCenters() {
		return centers;
	}

	public void setCenters(List<Center> centers) {
		this.centers = centers;
	}
}

Vytvoříme jednotlivé Java objekty a naplníme je daty. Jinak řečeno vytvoříme Company, která bude mít několik místností k pronájmu ve dvou kancelářských centrech. Vytvořenou Company převedeme do xml (mashall) a zase ji načteme zpět do Java objektů (unmashall).

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();
		}
	}

	/**
	 * Creates company and fills it with data.
	 * 
	 * @return	company
	 */
	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.setCenters(new ArrayList<>());
		company.getCenters().add(metronomPrague);
		company.getCenters().add(aviaticaPrague);

		return company;
	}
}

Nastavením vlastnosti JAXB_FORMATTED_OUTPUT na true řekneme, že xml dokument se má vygenerovat v lidsky čitelné formě (odsazení, konce řádek). Mashalovaný dokument můžeme vypsat i do konzole marshaller.marshal(createCompany(), System.out).

Takto vypadá vygenerovaný xml soubor (company.xml).

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<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>
        <rooms>
            <code>CA18</code>
            <numberOfSeats>24</numberOfSeats>
        </rooms>
        <rooms>
            <code>CB52</code>
            <numberOfSeats>88</numberOfSeats>
        </rooms>
        <rooms>
            <code>CD11</code>
            <numberOfSeats>62</numberOfSeats>
        </rooms>
    </centers>
</company>

Zde je výpis Company objektu, který jsme načetli pomocí unmarshall.

METPRG - Office center Metronom in Prague
room: A02	 number of seats: 14
room: A13	 number of seats: 42
room: B08	 number of seats: 22

AVIPRG - Office center Aviatica in Prague
room: AA41	 number of seats: 70
room: CA12	 number of seats: 38
room: CA18	 number of seats: 24
room: CB52	 number of seats: 88
room: CD11	 number of seats: 62

Zdroj:

Napsat komentář