W3docs

Java JAXB

Mapea XML a objetos Java y viceversa con anotaciones JAXB y Marshaller/Unmarshaller.

JAXB (Jakarta XML Binding, anteriormente Java Architecture for XML Binding) mapea objetos Java a XML y viceversa sin necesidad de escribir código de análisis a mano. Anotas una clase simple y la entregas a un Marshaller para producir XML o a un Unmarshaller para leer XML en objetos. JAXB vivía en el JDK (javax.xml.bind) hasta Java 8, fue eliminado en Java 11 y ahora se distribuye como una dependencia separada bajo el espacio de nombres jakarta.xml.bind. Las anotaciones y el modelo de marshal/unmarshal son los mismos en ambos casos.

Este capítulo cubre qué es el enlace JAXB, las anotaciones principales, cómo convertir un objeto a XML y leer XML de vuelta, cómo se mapean las colecciones y el cambio de espacio de nombres entre Java 8 y las versiones modernas de Java. JAXB es una API de enlace: a diferencia de los parsers de bajo nivel DOM y SAX cubiertos antes en esta parte, nunca tocas el árbol XML — trabajas con objetos Java ordinarios.

Cuándo usar JAXB

Usa JAXB cuando tus datos ya tienen (o merecen) una clase y XML es simplemente el formato de transporte o almacenamiento:

  • Leer y escribir archivos de configuración o documentos donde la estructura es estable y conocida de antemano.
  • Servicios web SOAP / heredados, donde el contrato es un esquema XML y las herramientas generan las clases.
  • Ida y vuelta — cargar XML, mutar el objeto y volver a escribirlo sin análisis manual.

Usa DOM o SAX cuando la estructura es irregular, solo necesitas unos pocos campos de un documento grande o no existe una clase natural a la que enlazar. Y si controlas ambos extremos y solo necesitas un formato de datos compacto, JSON con Jackson suele ser más ligero que XML.

La idea central: las anotaciones describen el mapeo

No escribes código que recorra el árbol XML. En su lugar, describes con anotaciones en una clase cómo sus campos corresponden a elementos y atributos XML. JAXB lee esas anotaciones en tiempo de ejecución y genera la conversión por ti en ambas direcciones. Un POJO se convierte en un esquema autodocumentado.

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

Las anotaciones principales

Un puñado de anotaciones cubre casi todos los mapeos. Viven en el paquete jakarta.xml.bind.annotation (o javax.xml.bind.annotation en Java 8).

AnotaciónEfecto
@XmlRootElementMarca una clase como raíz del documento; nombra el elemento más externo
@XmlElementMapea un campo/propiedad a un elemento anidado
@XmlAttributeMapea un campo/propiedad a un atributo en su elemento
@XmlElementWrapperEnvuelve una colección en un elemento contenedor
@XmlTransientExcluye un campo del XML por completo
@XmlAccessorTypeControla si JAXB enlaza campos o getters por defecto

Marshalling: objeto a XML

Un JAXBContext es el punto de entrada — créalo para tus clases raíz y luego pídele un Marshaller. El marshaller convierte un grafo de objetos en XML. Configurar JAXB_FORMATTED_OUTPUT produce una salida legible e indentada.

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

La operación inversa es simétrica: pídele al mismo JAXBContext un Unmarshaller y apúntalo a una fuente — un File, InputStream, Reader o StringReader. JAXB construye el objeto usando el constructor sin argumentos y lo rellena con los elementos y atributos.

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 no está en el classpath de este ejecutor de código (es una dependencia externa en Java moderno), por lo que el ejemplo práctico a continuación demuestra el mismo ciclo de marshal/unmarshal de ida y vuelta usando únicamente la API DOM integrada del JDK. El concepto es idéntico: un atributo en la raíz, elementos hijos para los campos y un viaje de regreso a un objeto igual.

java— editable, runs on the server

Qué extraer de la ejecución:

  • El XML marshalled coloca year como un atributo en <book> pero title y author como elementos hijos — exactamente la división que controlan @XmlAttribute versus @XmlElement en JAXB real. La elección de anotación es la que decide elemento-vs-atributo.
  • La etiqueta raíz es book, reportada por el.getTagName(). En JAXB ese nombre proviene de @XmlRootElement(name = "book"); aquí es la cadena pasada a createElement. De cualquier manera, el elemento más externo identifica el tipo del documento.
  • Marshalling y unmarshalling son operaciones espejo sobre la misma estructura: el programa construye XML a partir de un Book, luego reconstruye un Book desde ese XML. El Marshaller y el Unmarshaller de JAXB son exactamente este par, respaldados por un único JAXBContext.
  • round-trip equal : true prueba que los datos sobrevivieron el viaje intactos — título, autor y año regresaron todos. Un enlace correcto no tiene pérdidas, que es la propiedad en la que confías cuando XML es tu formato de transporte.
  • Leer year de vuelta requirió Integer.parseInt porque XML es todo texto. JAXB oculta esto convirtiendo el texto de atributos y elementos al tipo Java declarado (int, LocalDate, BigDecimal) automáticamente; sin él, cada campo es una cadena que debes analizar tú mismo.

Mapeo de colecciones

Un List se mapea a elementos repetidos. Por defecto cada elemento recibe el nombre del campo, lo que puede producir un documento plano y difícil de leer. @XmlElementWrapper agrega un elemento contenedor para que los elementos queden agrupados — el patrón común y legible.

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

Con el wrapper, la salida se anida limpiamente:

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

Elimina @XmlElementWrapper y los elementos <book> quedan directamente bajo <library> sin ningún elemento agrupador — válido, pero más plano. Elegir entre los dos es la decisión de mapeo de colecciones más común en JAXB.

Java 8 vs. Java moderno: el cambio de espacio de nombres

El mayor problema es el cambio de nombre del paquete. En Java 8 la API está incluida y vive bajo javax.xml.bind. A partir de Java 11 está desvinculada y vive bajo jakarta.xml.bind, incorporada como dependencia.

Java 8Java 11+
Paquetejavax.xml.bindjakarta.xml.bind
¿En el classpath?IntegradoAgregar una dependencia
Artefacto de tiempo de ejecuciónJDKorg.glassfish.jaxb:jaxb-runtime

Para una compilación Maven en Java moderno, agregas la API más una implementación de tiempo de ejecución:

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

Práctica

Práctica
En JAXB, ¿cuál es la diferencia entre anotar una propiedad con @XmlElement versus @XmlAttribute?
En JAXB, ¿cuál es la diferencia entre anotar una propiedad con @XmlElement versus @XmlAttribute?

Ver también

Was this page helpful?