Sérialisation et désérialisation XML avec Jackson

1. Vue d'ensemble

Dans ce didacticiel, nous allons voir comment sérialiser des objets Java en données XML à l'aide de Jackson 2.x et les désérialiser en POJO .

Nous allons nous concentrer sur l'opération de base qui ne nécessite pas beaucoup de complexité ou de personnalisation.

2. Objet XmlMapper

XmlMapper est la classe principale de Jackson 2.x qui nous aide dans la sérialisation, nous devrons donc en créer une instance:

XmlMapper mapper = new XmlMapper();

Ce mappeur est disponible dans le jar jackson-dataformat-xml , nous devons donc l'ajouter en tant que dépendance à notre pom.xml :

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

Veuillez vérifier la dernière version de la dépendance jackson-dataformat-xml dans le référentiel Maven.

3. Sérialiser Java en XML

XmlMapper est une sous-classe d' ObjectMapper qui est utilisée dans la sérialisation JSON. Cependant, il ajoute quelques modifications spécifiques à XML à la classe parente.

Nous pouvons maintenant voir comment l'utiliser pour effectuer la sérialisation réelle. Créons d'abord une classe Java:

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

3.1. Sérialiser à la chaîne XML

Nous pouvons sérialiser notre objet Java dans la chaîne XML :

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

En conséquence, nous obtiendrons:

 1 2 

3.2. Sérialiser dans le fichier XML

Nous pouvons également sérialiser notre objet Java dans le fichier 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); }

Et ci-dessous, nous pouvons voir le contenu du fichier résultant nommé simple_bean.xml :

 1 2 

4. Désérialiser XML en Java

Dans cette section, nous verrons comment obtenir des objets Java à partir de XML.

4.1. Désérialiser à partir de la chaîne XML

Comme pour la sérialisation, nous pouvons également désérialiser une chaîne XML en un objet 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. Désérialiser à partir du fichier XML

De même, si nous avons un fichier XML, nous pouvons le reconvertir en objet Java.

Ici, nous lisons d'abord le fichier dans un flux d'entrée, puis convertissons le flux d'entrée en une chaîne avec une méthode utilitaire simple.

Le reste du code est similaire à celui de la section 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); }

La méthode utilitaire:

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. Gestion des éléments capitalisés

Dans cette section, nous verrons comment gérer les scénarios dans lesquels nous avons soit du XML avec des éléments en majuscules à désérialiser, soit nous devons sérialiser des objets Java en XML avec un ou plusieurs éléments en majuscules.

5.1. Désérialiser à partir de la chaîne XML

Disons que nous avons un XML avec un champ en majuscule:

 1 2 

Afin de gérer correctement les éléments en majuscules, nous devons annoter le champ «x» avec l' annotation @JsonProperty :

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

Nous pouvons maintenant désérialiser correctement une chaîne XML en un objet 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. Sérialiser à la chaîne XML

En annotant les champs obligatoires avec @JsonProperty, nous pouvons correctement sérialiser un objet Java en une chaîne XML avec un ou plusieurs éléments en majuscules:

@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. Sérialiser la liste en XML

Le XmlMapper est capable de sérialiser un bean Java entier dans un document. Pour convertir un objet Java en XML, nous prendrons un exemple simple avec l'objet imbriqué et les tableaux.

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 s'occupe du reste pour nous. Comme avant, nous pouvons simplement appeler à nouveau writeValue :

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. Désérialiser XML dans la liste

Jackson peut également lire du XML contenant des listes d'objets.

Si nous prenons notre même XML qu'avant, la méthode readValue fonctionne très 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. Conclusion

Cet article simple a illustré comment sérialiser un POJO simple en XML et obtenir un POJO à partir de données XML de base.

Nous avons également examiné comment sérialiser et désérialiser des beans complexes contenant des collections.

Le code source qui accompagne cet article est disponible sur GitHub.