W3docs

Java JAXB

XML auf Java-Objekte abbilden und zurück mit JAXB-Annotationen, Marshaller und Unmarshaller.

JAXB (Jakarta XML Binding, früher Java Architecture for XML Binding) bildet Java-Objekte auf XML ab und umgekehrt, ohne dass Sie manuell Parsing-Code schreiben müssen. Sie annotieren eine einfache Klasse und übergeben sie dann einem Marshaller, um XML zu erzeugen, oder einem Unmarshaller, um XML in Objekte einzulesen. JAXB war im JDK (javax.xml.bind) bis Java 8 enthalten, wurde in Java 11 entfernt und wird nun als separate Abhängigkeit unter dem Namespace jakarta.xml.bind bereitgestellt. Die Annotationen und das Marshal-/Unmarshal-Modell sind in beiden Versionen identisch.

Dieses Kapitel behandelt das JAXB-Binding, die wichtigsten Annotationen, das Marshalling eines Objekts zu XML und das Unmarshalling von XML zurück in Objekte, die Abbildung von Collections sowie die Namespace-Änderung zwischen Java 8 und modernem Java. JAXB ist eine Binding-API: Anders als die Low-Level-Parser DOM und SAX, die früher in diesem Teil behandelt wurden, berühren Sie den XML-Baum nie — Sie arbeiten mit gewöhnlichen Java-Objekten.

Wann JAXB einsetzen

Verwenden Sie JAXB, wenn Ihre Daten bereits eine Klasse haben (oder eine verdienen) und XML lediglich das Übertragungsformat oder das Speicherformat ist:

  • Lesen und Schreiben von Konfigurations- oder Dokumentdateien, bei denen die Struktur stabil und im Voraus bekannt ist.
  • SOAP / Legacy-Webservices, bei denen der Vertrag ein XML-Schema ist und Werkzeuge die Klassen generieren.
  • Round-Tripping — XML laden, das Objekt verändern und ohne manuelles Parsing wieder zurückschreiben.

Greifen Sie stattdessen auf DOM oder SAX zurück, wenn die Struktur unregelmäßig ist, Sie nur wenige Felder aus einem großen Dokument benötigen oder keine natürliche Klasse zum Binden existiert. Und wenn Sie beide Seiten kontrollieren und nur ein kompaktes Datenformat benötigen, ist JSON mit Jackson in der Regel schlanker als XML.

Die Grundidee: Annotationen beschreiben das Mapping

Sie schreiben keinen Code, der den XML-Baum durchläuft. Stattdessen beschreiben Sie mit Annotationen an einer Klasse, wie deren Felder XML-Elementen und Attributen entsprechen. JAXB liest diese Annotationen zur Laufzeit und erzeugt die Konvertierung für Sie in beide Richtungen. Ein POJO wird zum selbstdokumentierenden Schema.

import jakarta.xml.bind.annotation.XmlRootElement;
import jakarta.xml.bind.annotation.XmlElement;
import jakarta.xml.bind.annotation.XmlAttribute;

@XmlRootElement(name = "book")
public class Book {
    private String title;
    private String author;
    private int year;

    @XmlElement public String getTitle() { return title; }
    public void setTitle(String title) { this.title = title; }

    @XmlElement public String getAuthor() { return author; }
    public void setAuthor(String author) { this.author = author; }

    @XmlAttribute public int getYear() { return year; }
    public void setYear(int year) { this.year = year; }

    // JAXB requires a public no-arg constructor for unmarshalling
    public Book() {}
}

Die wichtigsten Annotationen

Eine Handvoll Annotationen deckt nahezu jedes Mapping ab. Sie befinden sich im Paket jakarta.xml.bind.annotation (oder javax.xml.bind.annotation in Java 8).

AnnotationWirkung
@XmlRootElementMarkiert eine Klasse als Dokumentwurzel; benennt das äußerste Element
@XmlElementBildet ein Feld/eine Eigenschaft auf ein verschachteltes Element ab
@XmlAttributeBildet ein Feld/eine Eigenschaft auf ein Attribut seines Elements ab
@XmlElementWrapperUmschließt eine Collection mit einem übergeordneten Element
@XmlTransientSchließt ein Feld vollständig aus dem XML aus
@XmlAccessorTypeSteuert, ob JAXB standardmäßig Felder oder Getter bindet

Marshalling: Objekt zu XML

Ein JAXBContext ist der Einstiegspunkt — erstellen Sie einen für Ihre Root-Klassen, und fragen Sie dann nach einem Marshaller. Der Marshaller wandelt einen Objektgraphen in XML um. Das Setzen von JAXB_FORMATTED_OUTPUT liefert ein menschenlesbares, eingerücktes Ergebnis.

import jakarta.xml.bind.JAXBContext;
import jakarta.xml.bind.Marshaller;

Book book = new Book();
book.setTitle("Effective Java");
book.setAuthor("Joshua Bloch");
book.setYear(2018);

JAXBContext context = JAXBContext.newInstance(Book.class);
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(book, System.out);
// <book year="2018"><title>Effective Java</title><author>Joshua Bloch</author></book>

Unmarshalling: XML zu Objekt

Der umgekehrte Vorgang ist symmetrisch: Fordern Sie vom selben JAXBContext einen Unmarshaller an und verweisen Sie ihn auf eine Quelle — eine File, einen InputStream, einen Reader oder einen StringReader. JAXB erstellt das Objekt mit dem No-Arg-Konstruktor und befüllt es aus den Elementen und Attributen.

import jakarta.xml.bind.Unmarshaller;
import java.io.StringReader;

String xml = "<book year=\"2018\">"
           + "<title>Effective Java</title>"
           + "<author>Joshua Bloch</author></book>";

Unmarshaller unmarshaller = context.createUnmarshaller();
Book book = (Book) unmarshaller.unmarshal(new StringReader(xml));
System.out.println(book.getTitle()); // Effective Java
System.out.println(book.getYear());  // 2018

JAXB ist im Classpath dieses Code-Runners nicht verfügbar (es ist eine externe Abhängigkeit in modernem Java). Das nachfolgende Beispiel demonstriert daher denselben Marshal-/Unmarshal-Round-Trip ausschließlich mit der integrierten DOM-API des JDK. Das Konzept ist identisch: ein Attribut am Root-Element, Child-Elemente für die Felder und ein Round-Trip zurück zu einem gleichwertigen Objekt.

java— editable, runs on the server

Was aus der Ausführung zu entnehmen ist:

  • Das gemarshalte XML setzt year als Attribut auf <book>, während title und author Child-Elemente sind — genau die Aufteilung, die in echtem JAXB @XmlAttribute gegenüber @XmlElement steuert. Die Wahl der Annotation entscheidet zwischen Element und Attribut.
  • Das Root-Tag lautet book, wie el.getTagName() meldet. In JAXB stammt dieser Name aus @XmlRootElement(name = "book"); hier ist es der an createElement übergebene String. In beiden Fällen identifiziert das äußerste Element den Typ des Dokuments.
  • Marshalling und Unmarshalling sind Spiegeloperationen auf derselben Form: Das Programm erstellt XML aus einem Book und rekonstruiert dann aus diesem XML ein Book. JAXBs Marshaller und Unmarshaller bilden genau dieses Paar, gestützt auf einen JAXBContext.
  • round-trip equal : true beweist, dass die Daten den Weg unbeschadet überstanden haben — Titel, Autor und Jahr kamen alle zurück. Ein korrektes Binding ist verlustfrei, und das ist die Eigenschaft, auf die Sie sich verlassen, wenn XML Ihr Übertragungsformat ist.
  • Das Rücklesen von year erforderte Integer.parseInt, weil XML durchgehend Text ist. JAXB verbirgt dies, indem es Attribut- und Elementtext automatisch in den deklarierten Java-Typ (int, LocalDate, BigDecimal) umwandelt; ohne JAXB ist jedes Feld ein String, den Sie selbst parsen müssen.

Collections abbilden

Eine List wird auf wiederholte Elemente abgebildet. Standardmäßig wird jedes Element nach dem Feld benannt, was ein flaches, schwer lesbares Dokument erzeugen kann. @XmlElementWrapper fügt ein übergeordnetes Element hinzu, sodass die Einträge gruppiert werden — das übliche, lesbare Muster.

import jakarta.xml.bind.annotation.XmlRootElement;
import jakarta.xml.bind.annotation.XmlElement;
import jakarta.xml.bind.annotation.XmlElementWrapper;
import java.util.List;

@XmlRootElement(name = "library")
public class Library {
    private List<Book> books;

    @XmlElementWrapper(name = "books") // outer <books> element
    @XmlElement(name = "book")         // each item is a <book>
    public List<Book> getBooks() { return books; }
    public void setBooks(List<Book> books) { this.books = books; }

    public Library() {}
}

Mit dem Wrapper ist die Ausgabe sauber verschachtelt:

<library>
  <books>
    <book year="2018"><title>Effective Java</title>...</book>
    <book year="2008"><title>Clean Code</title>...</book>
  </books>
</library>

Lässt man @XmlElementWrapper weg, liegen die <book>-Elemente direkt unter <library> ohne Gruppierungselement — gültig, aber flacher. Die Entscheidung zwischen beiden ist die häufigste Collection-Mapping-Entscheidung in JAXB.

Java 8 vs. modernes Java: die Namespace-Verschiebung

Der größte Stolperstein ist die Paketumbenennung. In Java 8 ist die API eingebaut und befindet sich unter javax.xml.bind. Ab Java 11 ist sie ausgelagert und befindet sich unter jakarta.xml.bind, wo sie als Abhängigkeit eingebunden wird.

Java 8Java 11+
Paketjavax.xml.bindjakarta.xml.bind
Im Classpath?EingebautAbhängigkeit hinzufügen
Laufzeit-ArtefaktJDKorg.glassfish.jaxb:jaxb-runtime

Für einen Maven-Build auf modernem Java fügen Sie die API sowie eine Laufzeitimplementierung hinzu:

<dependency>
    <groupId>jakarta.xml.bind</groupId>
    <artifactId>jakarta.xml.bind-api</artifactId>
    <version>4.0.2</version>
</dependency>
<dependency>
    <groupId>org.glassfish.jaxb</groupId>
    <artifactId>jaxb-runtime</artifactId>
    <version>4.0.5</version>
</dependency>

Übungen

Übung
Was ist in JAXB der Unterschied zwischen der Annotation @XmlElement und @XmlAttribute an einer Eigenschaft?
Was ist in JAXB der Unterschied zwischen der Annotation @XmlElement und @XmlAttribute an einer Eigenschaft?

Siehe auch

Was this page helpful?