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: