W3docs

Java JAXB

Map XML to Java objects and back in Java with JAXB annotations and Marshaller/Unmarshaller.

Java JAXB

JAXB (Jakarta XML Binding, formerly Java Architecture for XML Binding) maps Java objects to XML and back without you writing parsing code by hand. You annotate a plain class, then hand it to a Marshaller to produce XML or an Unmarshaller to read XML into objects. JAXB lived in the JDK (javax.xml.bind) through Java 8, was removed in Java 11, and now ships as a separate dependency under the jakarta.xml.bind namespace. The annotations and the marshal/unmarshal model are the same in both.

The big idea: annotations describe the mapping

You do not write code that walks the XML tree. Instead you describe, with annotations on a class, how its fields correspond to XML elements and attributes. JAXB reads those annotations at runtime and generates the conversion for you in both directions. A POJO becomes a self-documenting 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() {}
}

The core annotations

A handful of annotations cover almost every mapping. They live in the jakarta.xml.bind.annotation package (or javax.xml.bind.annotation on Java 8).

AnnotationEffect
@XmlRootElementMarks a class as a document root; names the outermost element
@XmlElementMaps a field/property to a nested element
@XmlAttributeMaps a field/property to an attribute on its element
@XmlElementWrapperWraps a collection in a containing element
@XmlTransientExcludes a field from the XML entirely
@XmlAccessorTypeControls whether JAXB binds fields or getters by default

Marshalling: object to XML

A JAXBContext is the entry point — create one for your root classes, then ask it for a Marshaller. The marshaller turns an object graph into XML. Setting JAXB_FORMATTED_OUTPUT gives human-readable, indented output.

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 to object

The reverse is symmetric: ask the same JAXBContext for an Unmarshaller and point it at a source — a File, InputStream, Reader, or StringReader. JAXB constructs the object using the no-arg constructor and populates it from the elements and attributes.

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 is not on this code runner's classpath (it is an external dependency on modern Java), so the worked example below demonstrates the same marshal/unmarshal round trip using only the JDK's built-in DOM API. The concept is identical: an attribute on the root, child elements for the fields, and a round trip back to an equal object.

java— editable, runs on the server

What to take from the run:

  • The marshalled XML puts year as an attribute on <book> but title and author as child elements — exactly the split that @XmlAttribute versus @XmlElement controls in real JAXB. The annotation choice is what decides element-vs-attribute.
  • The root tag is book, reported by el.getTagName(). In JAXB that name comes from @XmlRootElement(name = "book"); here it is the string passed to createElement. Either way, the outermost element identifies the document's type.
  • Marshalling and unmarshalling are mirror operations on the same shape: the program builds XML from a Book, then reconstructs a Book from that XML. JAXB's Marshaller and Unmarshaller are this exact pair backed by one JAXBContext.
  • round-trip equal : true proves the data survived the trip intact — title, author, and year all came back. A correct binding is loss-free, which is the property you rely on when XML is your wire format.
  • Reading year back required Integer.parseInt because XML is all text. JAXB hides this by converting attribute and element text to the declared Java type (int, LocalDate, BigDecimal) automatically; without it, every field is a string you must parse yourself.

Java 8 vs. modern Java: the namespace move

The single biggest gotcha is the package rename. On Java 8 the API is bundled and lives under javax.xml.bind. From Java 11 onward it is unbundled and lives under jakarta.xml.bind, pulled in as a dependency.

Java 8Java 11+
Packagejavax.xml.bindjakarta.xml.bind
On the classpath?Built inAdd a dependency
Runtime artifactJDKorg.glassfish.jaxb:jaxb-runtime

For a Maven build on modern Java, you add the API plus a runtime implementation:

<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>

Practice

Practice

In JAXB, what is the difference between annotating a property with @XmlElement versus @XmlAttribute?