"Não tão rápido, jovem! Tenho mais duas aulas para você!"

"Dois? Uau. Bem, tudo bem. O que você não faria para melhorar sua própria frieza! Sou todo ouvidos."

"O XML, assim como o JSON, é frequentemente usado ao passar dados entre diferentes programas e computadores. E existem vários frameworks que simplificam muito a vida dos programadores Java ao trabalhar com XML. Hoje vou apresentar um deles."

"JAXB é uma estrutura multiuso excelente para trabalhar com XML."

JAXB - 1

"JAXB faz parte do JDK, então você não precisa baixá-lo separadamente."

"Deixe-me primeiro mostrar um exemplo de como usá-lo e depois vamos analisá-lo. Por exemplo:"

Converter um objeto para XML
public static void main(String[] args) throws JAXBException
{
 // Create an object to be serialized into XML
 Cat cat = new Cat();
 cat.name = "Missy";
 cat.age = 5;
 cat.weight = 4;

 // Write the result of the serialization to a StringWriter
 StringWriter writer = new StringWriter();

 // Create a Marshaller object that will perform the serialization
 JAXBContext context = JAXBContext.newInstance(Cat.class);
 Marshaller marshaller = context.createMarshaller();
 marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
 // And here's the serialization itself:
 marshaller.marshal(cat, writer);

 // Convert everything written to the StringWriter
 String result = writer.toString();
 System.out.println(result);
}
Uma classe cujos objetos são convertidos em XML
@XmlType(name = "cat")
@XmlRootElement
public class Cat
{
 public String name;
 public int age;
 public int weight;

 public Cat()
 {
 }
}
Resultado da serialização e saída da tela:
<cat> 
<name> Missy </name> 
<age> 5 </age> 
<weight> 4 </weight> 
</cat>

"Por alguma razão, linha por linha, este código me lembra a serialização JSON. As mesmas anotações, mas JSON usou um ObjectMapper, e este usa Context e Marshaller."

"Sim. Eles realmente são muito semelhantes. Jackson foi modelado após JAXB. Mas JAXB também foi copiado de algum lugar. Você não pode inventar algo genial do zero."

"Parece que sim."

"OK, aqui está o que está acontecendo:"

"Nas linhas 4-7, criamos um objeto Cat e o preenchemos com dados."

"Na linha 10, criamos um objeto Writer para escrever o resultado."

"Na linha 13, criamos o 'contexto'. Isso é semelhante ao ObjectMapper, mas dois objetos filhos adicionais são criados a partir dele. Marshaller é para serialização e Unmarshaller é para desserialização. Existem pequenas diferenças em relação a Jackson, mas não é não é fundamentalmente diferente."

"Na linha 14, criamos um objeto Marshaller . Marshalling é sinônimo de serialização."

"Na linha 15, definimos a propriedade FORMATTED_OUTPUT como TRUE. Isso adicionará quebras de linha e espaços ao resultado, para que o código seja legível por humanos e não tenha apenas todo o texto em uma linha."

"Na linha 17, serializamos o objeto."

"Nas linhas 20-21, exibimos o resultado da serialização na tela."

"O que são as anotações @XmlType(name = 'cat&') e @XmlRootElement?"

" @XmlRootElement indica que este objeto pode ser a 'raiz de uma árvore' de elementos XML. Em outras palavras, pode ser o elemento de nível mais alto e pode conter todos os outros elementos."

" @XmlType(name = 'cat') indica que a classe está envolvida na serialização JAXB e também especifica o nome da marca XML para esta classe."

"Tudo bem, agora vou mostrar um exemplo de desserialização de XML:"

Converter um objeto de XML
public static void main(String[] args) throws JAXBException
{
 String xmldata = "<cat><name>Missy</name><age>5</age><weight>4</weight></cat>";
 StringReader reader = new StringReader(xmldata);

 JAXBContext context = JAXBContext.newInstance(Cat.class);
 Unmarshaller unmarshaller = context.createUnmarshaller();

 Cat cat = (Cat) unmarshaller.unmarshal(reader);
}
Uma classe cujos objetos são desserializados de XML
@XmlType(name = "cat")
@XmlRootElement
public class Cat
{
 public String name;
 public int age;
 public int weight;

 public Cat()
 {
 }
}

"Tudo é quase o mesmo que com Jackson. Mas, por via das dúvidas, vou explicar tudo o que está acontecendo aqui."

"Na linha 3, passamos uma string que armazena o XML a ser desserializado."

"Na linha 4, envolvemos a string XML em um StringReader ."

"Na linha 6, criamos um contexto JAXB , para o qual passamos a lista de classes."

"Na linha 7, criamos um Unmarshaller — o objeto que executará a desserialização."

"Na linha 9, desserializamos o XML do objeto leitor e obtemos um objeto Cat."

"Agora tudo parece quase óbvio. Mas algumas horas atrás, eu estava quebrando a cabeça para descobrir como isso funciona."

"Isso sempre acontece quando você fica mais esperto. Coisas complexas se tornam simples."

"Estou ficando mais inteligente? Não posso deixar de ficar feliz com isso."

"Ótimo. Aqui está uma lista de anotações que você pode usar para controlar o resultado da serialização JAXB:"

anotações JAXB Descrição
@XmlElement(nome) Colocado perto de um campo.
O campo será armazenado em um elemento XML.
Permite definir o nome da tag.
@XmlAttribute(nome) Colocado perto de um campo.
O campo será armazenado como um atributo XML!
Permite definir o nome do atributo.
@XmlElementWrapper(nível = verdadeiro) Colocado perto de um campo.
Permite definir uma 'tag wrapper' para um grupo de elementos.
@XmlType Colocado perto de uma classe.
Permite especificar um método para criar um objeto se o construtor padrão for privado.
@XmlJavaTypeAdapter Colocado perto de um campo.
Permite especificar a classe que converterá o campo em uma string.

"Que interessante! Mas você pode me fornecer um exemplo que usa essas anotações? Uma explicação é uma coisa, mas um exemplo prático é outra."

"OK. Vou mostrar um exemplo. Só queria acrescentar que o JAXB permite anotar métodos getter/setter em vez de campos."

"Aqui está o exemplo que prometi:"

Converter um objeto para XML
public static void main(String[] args) throws JAXBException
{
 // Create Cat and Zoo objects to be serialized into XML
 Cat cat = new Cat();
 cat.name = "Missy";
 cat.age = 5;
 cat.weight = 4;

 Zoo zoo = new Zoo();
 zoo.animals.add(cat);
 zoo.animals.add(cat);

 // Write the result of the serialization to a StringWriter
 StringWriter writer = new StringWriter();

 // Create a Marshaller object that will perform the serialization
 JAXBContext context = JAXBContext.newInstance(Cat.class, Zoo.class);
 Marshaller marshaller = context.createMarshaller();
 marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
 // Here's the serialization itself
 marshaller.marshal(zoo, writer);

 // Convert everything written to the StringWriter into a String
 System.out.println(writer.toString());
}
Uma classe cujos objetos são convertidos em XML
@XmlType(name = "zoo")
@XmlRootElement
public class Zoo
{
 @XmlElementWrapper(name = "wild-animals", nillable = true)
 @XmlElement(name = "tiger")
 public List<Cat> animals = new ArrayList<>();
}

public class Cat
{
 @XmlElement(name = "catname")
 public String name;
 @XmlAttribute(name = "age")
 public int age;
 @XmlAttribute(name = "w")
 public int weight;

 public Cat()
 {
 }
}
Resultado da serialização e saída da tela:
<zoo> 
<wild-animals> 
<tiger age = "5" w = "4"> 
<catname>Missy</catname> 
</tiger> 
<tiger age = "5" w = "4"> 
<catname>Missy </catname> 
</tiger> 
</wild-animals> 
</zoo>

"Observe que desta vez não estamos serializando um objeto Cat, mas um objeto Zoo que armazena uma coleção de objetos Cat."

"O objeto cat foi adicionado à coleção duas vezes, então está no XML duas vezes."

"A coleção tem sua própria marca ' animais selvagens ' que envolve todos os elementos da coleção."

"Os elementos idade e peso tornaram-se os atributos idade e peso ."

"Usando um atributo @XmlElement , mudamos a tag cat para uma tag tiger ."

"Preste atenção na linha 17. Aqui passamos duas classes ( Zoo e Cat ) para o contexto JAXB, pois ambas estão envolvidas na serialização."

"Hoje foi um dia muito interessante. Tanta informação nova."

"Sim. Estou feliz por você. Agora, faça uma pequena pausa e continuaremos."