Serialización y deserialización XML con Jackson

1. Información general

En este tutorial, veremos cómo serializar objetos Java a datos XML usando Jackson 2.xy deserializarlos nuevamente en un POJO .

Nos centraremos en la operación básica que no requiere mucha complejidad o personalización.

2. Objeto XmlMapper

XmlMapper es la clase principal de Jackson 2.x que nos ayuda en la serialización, por lo que necesitaremos crear una instancia de la misma:

XmlMapper mapper = new XmlMapper();

Este mapeador está disponible en jackson-dataformat-xml jar, por lo que tenemos que agregarlo como una dependencia a nuestro pom.xml :

 com.fasterxml.jackson.dataformat jackson-dataformat-xml 2.11.1 

Verifique la última versión de la dependencia jackson-dataformat-xml en el repositorio de Maven.

3. Serializar Java a XML

XmlMapper es una subclase de ObjectMapper que se utiliza en la serialización JSON. Sin embargo, agrega algunos ajustes específicos de XML a la clase principal.

Ahora podemos ver cómo usarlo para realizar la serialización real. Primero creemos una clase Java:

class SimpleBean { private int x = 1; private int y = 2; //standard setters and getters }

3.1. Serializar en la cadena XML

Podemos serializar nuestro objeto Java en la cadena XML :

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

Como resultado obtendremos:

 1 2 

3.2. Serializar en el archivo XML

También podemos serializar nuestro objeto Java en el archivo 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); }

Y a continuación podemos ver el contenido del archivo resultante llamado simple_bean.xml :

 1 2 

4. Deserializar XML a Java

En esta sección, veremos cómo obtener objetos Java desde XML.

4.1. Deserializar de la cadena XML

Al igual que con la serialización, también podemos deserializar una cadena XML en un 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. Deserializar desde el archivo XML

Asimismo, si tenemos un archivo XML, podemos convertirlo de nuevo en un objeto Java.

Aquí, primero leemos el archivo en un flujo de entrada y luego convertimos el flujo de entrada en una cadena con un método de utilidad simple.

El resto del código es similar al de la sección 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); }

El método de utilidad:

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. Manejo de elementos en mayúscula

En esta sección, veremos cómo manejar escenarios en los que tenemos XML con elementos en mayúsculas para deserializar o necesitamos serializar objetos Java a XML con uno o más elementos en mayúsculas.

5.1. Deserializar de la cadena XML

Digamos que tenemos un XML con un campo en mayúscula:

 1 2 

Para manejar correctamente los elementos en mayúscula, necesitamos anotar el campo "x" con la anotación @JsonProperty :

class SimpleBeanForCapitalizedFields { @JsonProperty("X") private int x = 1; private int y = 2; // standard getters, setters }

Ahora podemos deserializar correctamente una cadena XML de nuevo a un 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 en la cadena XML

Al anotar los campos obligatorios con @JsonProperty, podemos serializar correctamente un objeto Java en una cadena XML con uno o más elementos en mayúscula:

@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. Serializar la lista en XML

El XmlMapper es capaz de serializar todo un bean Java en un documento. Para convertir un objeto Java a XML, tomaremos un ejemplo simple con el objeto anidado y las matrices.

Our intent is to serialize a Person object, along with its composed Address object, into XML.

Our final XML will look something like:

 Rohan Daye  9911034731 9911033478   Name1 City1   Name2 City2  

Notice that our phone numbers are encapsulated in a phoneNumbers wrapper while our address is not.

We can express this nuance via the @JacksonXMLElementWrapper annotation in our Person class:

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 }

Actually, we can change the wrapping element name with @JacksonXmlElementWrapper(localName = ‘phoneNumbers'). Or, if we don't want to wrap our elements, we can disable the mapping with @JacksonXmlElementWrapper(useWrapping = false).

And then let's define our Address type:

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

Jackson se encarga del resto por nosotros. Como antes, simplemente podemos llamar a writeValue nuevamente:

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. Deserializar XML a la lista

Jackson también puede leer XML que contiene listas de objetos.

Si tomamos nuestro mismo XML que antes, el método readValue funciona bien:

@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. Conclusión

Este sencillo artículo ilustró cómo serializar un POJO simple a XML y obtener un POJO a partir de datos XML básicos.

También hemos investigado cómo serializar y deserializar beans complejos que contienen colecciones.

El código fuente que acompaña a este artículo está disponible en GitHub.