W3docs

Java JAXB

Mapeie XML para objetos Java e vice-versa usando anotações JAXB e Marshaller/Unmarshaller em Java.

JAXB (Jakarta XML Binding, anteriormente Java Architecture for XML Binding) mapeia objetos Java para XML e vice-versa sem que você precise escrever código de análise manualmente. Você anota uma classe simples e a entrega a um Marshaller para produzir XML ou a um Unmarshaller para ler XML e convertê-lo em objetos. O JAXB existia no JDK (javax.xml.bind) até o Java 8, foi removido no Java 11 e agora é distribuído como uma dependência separada sob o namespace jakarta.xml.bind. As anotações e o modelo de marshal/unmarshal são iguais nos dois casos.

Este capítulo aborda o que é o binding JAXB, as anotações principais, como fazer marshal de um objeto para XML e unmarshal de XML de volta para objetos, como coleções são mapeadas e a mudança de namespace entre Java 8 e Java moderno. JAXB é uma API de binding: ao contrário dos parsers de nível mais baixo DOM e SAX abordados anteriormente nesta parte, você nunca toca a árvore XML — você trabalha com objetos Java comuns.

Quando usar JAXB

Use JAXB quando seus dados já possuem (ou merecem) uma classe, e XML é apenas o formato de transmissão ou armazenamento:

  • Leitura e escrita de arquivos de configuração ou documentos onde a estrutura é estável e conhecida com antecedência.
  • SOAP / serviços web legados, onde o contrato é um esquema XML e as ferramentas geram as classes.
  • Round-tripping — carregar XML, alterar o objeto e gravá-lo de volta sem análise manual.

Prefira DOM ou SAX quando a estrutura for irregular, você precisar apenas de alguns campos de um documento grande ou não houver uma classe natural para vincular. E se você controla ambos os lados e precisa apenas de um formato de dados compacto, JSON com Jackson costuma ser mais leve que XML.

A ideia principal: anotações descrevem o mapeamento

Você não escreve código que percorre a árvore XML. Em vez disso, você descreve, com anotações em uma classe, como seus campos correspondem a elementos e atributos XML. O JAXB lê essas anotações em tempo de execução e gera a conversão para você em ambas as direções. Um POJO se torna um 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() {}
}

As anotações principais

Um conjunto de anotações cobre quase todos os mapeamentos. Elas estão no pacote jakarta.xml.bind.annotation (ou javax.xml.bind.annotation no Java 8).

AnotaçãoEfeito
@XmlRootElementMarca uma classe como raiz do documento; nomeia o elemento mais externo
@XmlElementMapeia um campo/propriedade para um elemento aninhado
@XmlAttributeMapeia um campo/propriedade para um atributo no seu elemento
@XmlElementWrapperEnvolve uma coleção em um elemento contêiner
@XmlTransientExclui um campo do XML completamente
@XmlAccessorTypeControla se o JAXB vincula campos ou getters por padrão

Marshalling: objeto para XML

Um JAXBContext é o ponto de entrada — crie um para suas classes raiz e solicite um Marshaller. O marshaller transforma um grafo de objetos em XML. Definir JAXB_FORMATTED_OUTPUT produz saída legível 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 para objeto

O processo inverso é simétrico: solicite ao mesmo JAXBContext um Unmarshaller e aponte-o para uma fonte — um File, InputStream, Reader ou StringReader. O JAXB constrói o objeto usando o construtor sem argumentos e o preenche com os elementos e 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

O JAXB não está no classpath deste executor de código (é uma dependência externa no Java moderno), portanto o exemplo abaixo demonstra o mesmo round trip de marshal/unmarshal usando apenas a API DOM integrada do JDK. O conceito é idêntico: um atributo na raiz, elementos filhos para os campos e um round trip de volta a um objeto igual.

java— editable, runs on the server

O que observar na execução:

  • O XML serializado coloca year como um atributo em <book>, mas title e author como elementos filhos — exatamente a divisão que @XmlAttribute versus @XmlElement controla no JAXB real. A escolha da anotação é o que decide elemento-vs-atributo.
  • A tag raiz é book, relatada por el.getTagName(). No JAXB esse nome vem de @XmlRootElement(name = "book"); aqui é a string passada para createElement. De qualquer forma, o elemento mais externo identifica o tipo do documento.
  • Marshalling e unmarshalling são operações espelhadas sobre a mesma estrutura: o programa constrói XML a partir de um Book e depois reconstrói um Book a partir desse XML. O Marshaller e o Unmarshaller do JAXB são exatamente esse par, apoiados por um único JAXBContext.
  • round-trip equal : true prova que os dados sobreviveram à viagem intactos — título, autor e ano retornaram corretamente. Um binding correto é sem perdas, que é a propriedade em que você conta quando XML é seu formato de transmissão.
  • Ler year de volta exigiu Integer.parseInt porque XML é todo texto. O JAXB oculta isso convertendo o texto de atributos e elementos para o tipo Java declarado (int, LocalDate, BigDecimal) automaticamente; sem ele, cada campo é uma string que você precisa analisar manualmente.

Mapeamento de coleções

Um List mapeia para elementos repetidos. Por padrão, cada item é nomeado conforme o campo, o que pode produzir um documento plano e difícil de ler. @XmlElementWrapper adiciona um elemento contêiner para que os itens fiquem agrupados — o padrão comum e legível.

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

Com o wrapper, a saída fica aninhada de forma limpa:

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

Remova @XmlElementWrapper e os elementos <book> ficarão diretamente sob <library> sem nenhum elemento de agrupamento — válido, mas mais plano. Escolher entre os dois é a decisão de mapeamento de coleção mais comum no JAXB.

Java 8 vs. Java moderno: a mudança de namespace

O maior problema é a renomeação do pacote. No Java 8 a API está incluída e vive sob javax.xml.bind. A partir do Java 11 ela não está mais incluída e vive sob jakarta.xml.bind, sendo adicionada como dependência.

Java 8Java 11+
Pacotejavax.xml.bindjakarta.xml.bind
No classpath?IntegradoAdicionar dependência
Artefato em tempo de execuçãoJDKorg.glassfish.jaxb:jaxb-runtime

Para um build Maven no Java moderno, você adiciona a API mais uma implementação em tempo de execução:

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

Prática
No JAXB, qual é a diferença entre anotar uma propriedade com @XmlElement versus @XmlAttribute?
No JAXB, qual é a diferença entre anotar uma propriedade com @XmlElement versus @XmlAttribute?

Veja também

Was this page helpful?