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: