Serialização e desserialização de XML com Jackson

Serialização e desserialização de XML com Jackson

1. Visão geral

Neste tutorial, vamos dar uma olhada emhow to serialize Java objects to XML data using Jackson 2.x and deserialize it back to a POJO.

Vamos nos concentrar na operação básica que não requer muita complexidade ou personalização.

2. XmlMapper Objeto

XmlMapper é a classe principal do Jackson 2.x que nos ajuda na serialização, portanto, precisaremos criar uma instância dela:

XmlMapper mapper = new XmlMapper();

Estemapper  está disponível no jarjackson-dataformat-xml, então temos que adicioná-lo como uma dependência ao nossopom.xml:


    com.fasterxml.jackson.dataformat
    jackson-dataformat-xml
    2.9.8

3. Serializar Java para XML

XmlMapper é uma subclasse deObjectMapper que é usada na serialização JSON. No entanto, ele adiciona alguns ajustes específicos de XML à classe pai.

Agora podemos ver como usá-lo para fazer a serialização real. Vamos criar uma classe Java primeiro:

class SimpleBean {
    private int x = 1;
    private int y = 2;

    //standard setters and getters
}

3.1. Serializar para XMLString

Podemos serializar nosso objeto Java no XMLString:

@Test
public void whenJavaSerializedToXmlStr_thenCorrect() throws JsonProcessingException {
    XmlMapper xmlMapper = new XmlMapper();
    String xml = xmlMapper.writeValueAsString(new SimpleBean());
    assertNotNull(xml);
}

Como resultado, obteremos:


    1
    2

3.2. Serializar para o arquivo XML

Também podemos serializar nosso objeto Java no arquivo XML:

@Test
public void whenJavaSerializedToXmlFile_thenCorrect() throws IOException {
    XmlMapper xmlMapper = new XmlMapper();
    xmlMapper.writeValue(new File("simple_bean.xml"), new SimpleBean());
    File file = new File("simple_bean.xml");
    assertNotNull(file);
}

E abaixo podemos ver o conteúdo do arquivo resultante denominadosimple_bean.xml:


    1
    2

4. Desserializar XML para Java

Nesta seção, veremos como obter objetos Java de XML.

4.1. Desserializar da string XML

Assim como na serialização, também podemos desserializar uma String XML de volta para um objeto Java:

@Test
public void whenJavaGotFromXmlStr_thenCorrect() throws IOException {
    XmlMapper xmlMapper = new XmlMapper();
    SimpleBean value
      = xmlMapper.readValue("12", SimpleBean.class);
    assertTrue(value.getX() == 1 && value.getY() == 2);
}

4.2. Desserializar do arquivo XML

Da mesma forma, se tivermos um arquivo XML, podemos convertê-lo novamente em um objeto Java.

Aqui, primeiro lemos o arquivo em um fluxo de entrada e depois convertemos o fluxo de entrada emString com um método utilitário simples.

O restante do código é semelhante ao da seção 4.1:

@Test
public void whenJavaGotFromXmlFile_thenCorrect() throws IOException {
    File file = new File("simple_bean.xml");
    XmlMapper xmlMapper = new XmlMapper();
    String xml = inputStreamToString(new FileInputStream(file));
    SimpleBean value = xmlMapper.readValue(xml, SimpleBean.class);
    assertTrue(value.getX() == 1 && value.getY() == 2);
}

O método utilitário:

public String inputStreamToString(InputStream is) throws IOException {
    StringBuilder sb = new StringBuilder();
    String line;
    BufferedReader br = new BufferedReader(new InputStreamReader(is));
    while ((line = br.readLine()) != null) {
        sb.append(line);
    }
    br.close();
    return sb.toString();
}

5. Manipulação de elementos em maiúsculas

Nesta seção, veremos como lidar com cenários em que temos XML com elementos em maiúsculas para desserializar ou precisamos serializar objetos Java para XML com um ou mais elementos em maiúsculas.

5.1. Desserializar do XMLString

Digamos que temos um XML com um campo em maiúscula:


    1
    2

Para lidar corretamente com os elementos capitalizados, precisamos anotar o campo “x” com a anotação@JsonProperty:

class SimpleBeanForCapitalizedFields {
    @JsonProperty("X")
    private int x = 1;
    private int y = 2;

    // standard getters, setters
}

Agora podemos desserializar corretamente um XMLString de volta para um objeto Java:

@Test
public void whenJavaGotFromXmlStrWithCapitalElem_thenCorrect() throws IOException {
    XmlMapper xmlMapper = new XmlMapper();
    SimpleBeanForCapitalizedFields value
      = xmlMapper.readValue(
      "12",
      SimpleBeanForCapitalizedFields.class);
    assertTrue(value.getX() == 1 && value.getY() == 2);
}

5.2. Serializar para a string XML

Anotando os campos obrigatórios com@JsonProperty,, podemos serializar corretamente um objeto Java em um XMLString com um ou mais elementos em maiúsculas:

@Test
public void whenJavaSerializedToXmlFileWithCapitalizedField_thenCorrect()
  throws IOException {
    XmlMapper xmlMapper = new XmlMapper();
    xmlMapper.writeValue(new File("target/simple_bean_capitalized.xml"),
      new SimpleBeanForCapitalizedFields());
    File file = new File("target/simple_bean_capitalized.xml");
    assertNotNull(file);
}

6. Serialize List to XML

OXmlMapper é capaz de serializar um Java bean inteiro em um documento. Para converter o objeto Java em XML, vamos dar um exemplo simples com o objeto aninhado e matrizes.

Nossa intenção é serializar um objetoPerson, junto com seu objetoAddress composto, em XML.

Nosso XML final será parecido com:


    Rohan
    Daye
    
        9911034731
        9911033478
    
    
Name1 City1
Name2 City2

Observe que nossos números de telefone estão encapsulados em um wrapperphoneNumbers, enquanto nosso endereço não está.

Podemos expressar essa nuance por meio da anotação@JacksonXMLElementWrapper em nossa classePerson:

public final class Person {
    private String firstName;
    private String lastName;
    private List phoneNumbers = new ArrayList<>();
    @JacksonXmlElementWrapper(useWrapping = false)
    private List
address = new ArrayList<>(); //standard setters and getters }

Na verdade, podemos alterar o nome do elemento de empacotamento com@JacksonXmlElementWrapper(localName = ‘phoneNumbers'). Ou, se não quisermos encapsular nossos elementos, podemos desabilitar o mapeamento com@JacksonXmlElementWrapper(useWrapping = false).

E então vamos definir nosso tipoAddress :

public class Address {
    String streetName;
    String city;
    //standard setters and getters
}

Jackson takes care of the rest for us. Como antes, podemos simplesmente chamarwriteValue novamente:

private static final String XML = "...";

@Test
public void whenJavaSerializedToXmlFile_thenSuccess() throws IOException {
    XmlMapper xmlMapper = new XmlMapper();
    Person person = testPerson(); // test data
    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    xmlMapper.writeValue(byteArrayOutputStream, person);
    assertEquals(XML, byteArrayOutputStream.toString());
}

7. Desserializar XML paraList

Jackson também pode ler XML que contém listas de objetos.

Se pegarmos nosso mesmo XML de antes, o métodoreadValue funciona perfeitamente:

@Test
public void whenJavaDeserializedFromXmlFile_thenCorrect() throws IOException {
    XmlMapper xmlMapper = new XmlMapper();
    Person value = xmlMapper.readValue(XML, Person.class);
    assertEquals("City1", value.getAddress().get(0).getCity());
    assertEquals("City2", value.getAddress().get(1).getCity());
}

8. Conclusão

Este artigo simples ilustrou como serializar um POJO simples para XML e obter um POJO a partir de dados XML básicos.

Também analisamos como serializar e desserializar beans complexos que contêm coleções.

O código-fonte que acompanha este artigo está disponível emGitHub.