Serializzazione e deserializzazione XML con Jackson

1. Panoramica

In questo tutorial, vedremo come serializzare oggetti Java in dati XML usando Jackson 2.x e deserializzarli di nuovo in un POJO .

Ci concentreremo sull'operazione di base che non richiede molta complessità o personalizzazione.

2. Oggetto XmlMapper

XmlMapper è la classe principale di Jackson 2.x che ci aiuta nella serializzazione, quindi dovremo crearne un'istanza:

XmlMapper mapper = new XmlMapper();

Questo mappatore è disponibile nel jar jackson-dataformat-xml , quindi dobbiamo aggiungerlo come dipendenza al nostro pom.xml :

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

Controlla l'ultima versione della dipendenza jackson-dataformat-xml nel repository Maven.

3. Serializzare Java in XML

XmlMapper è una sottoclasse di ObjectMapper che viene utilizzata nella serializzazione JSON. Tuttavia, aggiunge alcune modifiche specifiche per XML alla classe genitore.

Ora possiamo vedere come usarlo per eseguire la serializzazione effettiva. Creiamo prima una classe Java:

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

3.1. Serializza nella stringa XML

Possiamo serializzare il nostro oggetto Java nella stringa XML :

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

Di conseguenza otterremo:

 1 2 

3.2. Serializza nel file XML

Possiamo anche serializzare il nostro oggetto Java nel file 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 di seguito possiamo vedere il contenuto del file risultante denominato simple_bean.xml :

 1 2 

4. Deserializzare XML in Java

In questa sezione vedremo come ottenere oggetti Java da XML.

4.1. Deserializza dalla stringa XML

Come con la serializzazione, possiamo anche deserializzare una stringa XML in un oggetto 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. Deserializza dal file XML

Allo stesso modo, se abbiamo un file XML, possiamo riconvertirlo in un oggetto Java.

Qui, prima leggiamo il file in un flusso di input e quindi convertiamo il flusso di input in una stringa con un semplice metodo di utilità.

Il resto del codice è simile a quello della sezione 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); }

Il metodo di utilità:

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. Gestione di elementi in maiuscolo

In questa sezione vedremo come gestire gli scenari in cui abbiamo XML con elementi in maiuscolo da deserializzare o abbiamo bisogno di serializzare oggetti Java in XML con uno o più elementi in maiuscolo.

5.1. Deserializza dalla stringa XML

Supponiamo di avere un XML con un campo in maiuscolo:

 1 2 

Per gestire correttamente gli elementi in maiuscolo, dobbiamo annotare il campo "x" con l' annotazione @JsonProperty :

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

Ora possiamo deserializzare correttamente una stringa XML in un oggetto 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. Serializza nella stringa XML

Annotando i campi obbligatori con @JsonProperty, possiamo serializzare correttamente un oggetto Java in una stringa XML con uno o più elementi in maiuscolo:

@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. Serializza elenco in XML

Il XmlMapper è in grado di serializzare un intero bean Java in un documento. Per convertire un oggetto Java in XML, faremo un semplice esempio con l'oggetto e gli array nidificati.

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 si prende cura del resto per noi. Come prima, possiamo semplicemente chiamare di nuovo 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. Deserializza XML in elenco

Jackson può leggere anche XML che contiene elenchi di oggetti.

Se prendiamo il nostro stesso XML di prima, il metodo readValue funziona bene:

@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. Conclusione

Questo semplice articolo ha illustrato come serializzare un semplice POJO in XML e ottenere un POJO da dati XML di base.

Abbiamo anche esaminato come serializzare e deserializzare i bean complessi che contengono raccolte.

Il codice sorgente che accompagna questo articolo è disponibile su GitHub.