Java XML et JSON: traitement de documents pour Java SE, partie 1: SAXON et Jackson

Précédent 1 2 Page 2 Page 2 de 2

Transformation

Essayons maintenant la transformation. Exécutez la commande suivante:

java XSLTDemo books.xml books.xsl

Malheureusement, cette transformation échoue: vous devez observer la sortie qui identifie Apache Xalan en tant que fabrique de transformateurs et un message d'erreur indiquant que ce xsl:for-each-groupn'est pas pris en charge.

Essayons encore. En supposant que saxon9he.jaret XSLTDemo.classse trouvent dans le répertoire courant, exécutez la commande suivante:

java -cp saxon9he.jar;. XSLTDemo books.xml books.xsl

Cette fois, vous devriez observer la sortie triée et correctement groupée suivante:

Addendum au chapitre 11: Traitement JSON avec Jackson

Conversion de XML en JSON avec Jackson

Java XML et JSON, chapitre 11, présente Jackson, qui fournit des API pour l'analyse et la création d'objets JSON. Il est également possible d'utiliser Jackson pour convertir des documents XML en documents JSON.

Dans cette section, je vais vous montrer deux façons de convertir XML en JSON, d'abord avec la liaison de données, puis avec la traversée d'arbre. Je suppose que vous avez lu le chapitre 11 et que vous connaissez Jackson. Pour suivre ces démos, vous devez avoir téléchargé les fichiers JAR suivants à partir du référentiel Maven:

  • jackson-annotations-2.9.7.jar
  • jackson-core-2.9.7.jar
  • jackson-databind-2.9.7.jar

Vous aurez également besoin de quelques fichiers JAR supplémentaires; la plupart sont communs aux deux techniques de conversion. Je vais vous fournir des informations sur l'obtention de ces fichiers JAR sous peu.

Convertir XML en JSON avec liaison de données

La liaison de données vous permet de mapper des données sérialisées à un objet Java. Par exemple, supposons que vous ayez un petit document XML qui décrit une seule planète. Le listing 4 présente ce document.

Liste 4. planet.xml

  Earth 3 9 

Le listing 5 présente une Planetclasse Java équivalente dont les objets correspondent au planet.xmlcontenu de.

Listing 5. Planet.java

public class Planet { public String name; public Integer planet_from_sun; public Integer moons; }

Le processus de conversion nécessite que vous analysiez d'abord le XML dans un Planetobjet. Vous pouvez accomplir cette tâche en travaillant avec la com.fasterxml.jackson.dataformat.xml.XmlMapperclasse, comme suit:

XmlMapper xmlMapper = new XmlMapper(); XMLInputFactory xmlif = XMLInputFactory.newFactory(); FileReader fr = new FileReader("planet.xml"); XMLStreamReader xmlsr = xmlif.createXMLStreamReader(fr); Planet planet = xmlMapper.readValue(xmlsr, Planet.class);

XmlMapperest un personnalisé com.fasterxml.jackson.databind.ObjectMapperqui lit et écrit du XML. Il fournit plusieurs readValue()méthodes pour lire une seule valeur XML à partir d'une source d'entrée spécifique à XML; par exemple:

 T readValue(XMLStreamReader r, Class valueType)

Chaque readValue()méthode requiert un javax.xml.stream.XMLStreamReaderobjet comme premier argument. Cet objet est essentiellement un analyseur basé sur le flux basé sur StAX pour analyser efficacement le texte de manière directe.

Le deuxième argument est un java.lang.Classobjet pour le type de cible qui est instancié, rempli de données XML et dont l'instance est ensuite renvoyée par la méthode.

L'essentiel de ce fragment de code est que le contenu du Listing 4 est lu dans un Planetobjet qui readValue()retourne à son appelant.

Une fois l'objet créé, il est facile de l'écrire en JSON en travaillant avec ObjectMapperet sa String writeValueAsString(Object value)méthode:

ObjectMapper jsonMapper = new ObjectMapper(); String json = jsonMapper.writeValueAsString(planet);

J'ai extrait ces fragments de code d'une XML2JSONapplication dont le code source complet apparaît dans le Listing 6.

Listing 6. XML2JSON.java (Version 1)

import java.io.FileReader; import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLStreamReader; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import static java.lang.System.*; public class XML2JSON { public static void main(String[] args) throws Exception { XmlMapper xmlMapper = new XmlMapper(); XMLInputFactory xmlif = XMLInputFactory.newFactory(); FileReader fr = new FileReader("planet.xml"); XMLStreamReader xmlsr = xmlif.createXMLStreamReader(fr); Planet planet = xmlMapper.readValue(xmlsr, Planet.class); ObjectMapper jsonMapper = new ObjectMapper(); String json = jsonMapper.writeValueAsString(planet); out.println(json); } }

Avant de pouvoir compiler les listes 5 et 6, vous devez télécharger Jackson Dataformat XML, qui implémente XMLMapper. J'ai téléchargé la version 2.9.7, qui correspond aux versions des trois autres packages Jackson.

En supposant que vous avez téléchargé avec succès jackson-dataformat-xml-2.9.7.jar, exécutez la commande suivante (répartie sur deux lignes pour plus de lisibilité) pour compiler le code source:

javac -cp jackson-core-2.9.7.jar;jackson-databind-2.9.7.jar;jackson-dataformat-xml-2.9.7.jar;. XML2JSON.java

Avant de pouvoir exécuter l'application résultante, vous devez télécharger Jackson Module: JAXB Annotations, ainsi que l'API StAX 2. J'ai téléchargé JAXB Annotations version 2.9.7 et StAX 2 API version 3.1.3.

En supposant que vous avez correctement téléchargé jackson-module-jaxb-annotations-2.9.7.jaret stax2-api-3.1.3.jar, exécutez la commande suivante (répartie sur trois lignes pour plus de lisibilité) pour exécuter l'application:

java -cp jackson-annotations-2.9.7.jar;jackson-core-2.9.7.jar;jackson-databind-2.9.7.jar; jackson-dataformat-xml-2.9.7.jar;jackson-module-jaxb-annotations-2.9.7.jar; stax2-api-3.1.3.jar;. XML2JSON

Si tout se passe bien, vous devriez observer le résultat suivant:

{"name":"Earth","planet_from_sun":3,"moons":9}

Convertir XML en JSON avec la traversée d'arbre

Une autre façon de convertir du XML en JSON consiste à analyser d'abord le XML dans une arborescence de nœuds JSON, puis à écrire cette arborescence dans un document JSON. Vous pouvez accomplir la première tâche en appelant l'une des méthodes XMLMapperhéritées de readTree():

XmlMapper xmlMapper = new XmlMapper(); JsonNode node = xmlMapper.readTree(xml.getBytes());

ObjectMapperLa JsonNode readTree(byte[] content)méthode de désérialise le contenu JSON dans une arborescence d' jackson.databind.JsonNodeobjets et retourne l' JsonNodeobjet racine de cet arbre. Dans un XmlMappercontexte, cette méthode désérialise le contenu XML dans l'arborescence. Dans les deux cas, le contenu JSON ou XML est passé à cette méthode sous la forme d'un tableau d'octets.

La deuxième tâche - convertir l'arborescence des objets en JSON - est accomplie d'une manière similaire à ce que j'ai montré précédemment. Cette fois, c'est l' JsonNodeobjet racine qui est passé à writeValueAsString():

ObjectMapper jsonMapper = new ObjectMapper(); String json = jsonMapper.writeValueAsString(node);

I excerpted these code fragments from an XML2JSON application whose complete source code appears in Listing 7.

Listing 7. XML2JSON.java (version 2)

import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import static java.lang.System.*; public class XML2JSON { public static void main(String[] args) throws Exception { String xml = "\n"+ "\n" + " Earth\n" + " 3\n" + " 1\n" + "\n"; XmlMapper xmlMapper = new XmlMapper(); JsonNode node = xmlMapper.readTree(xml.getBytes()); ObjectMapper jsonMapper = new ObjectMapper(); String json = jsonMapper.writeValueAsString(node); out.println(json); } }

Execute the following command (spread over two lines for readability) to compile Listing 7:

javac -cp jackson-core-2.9.7.jar;jackson-databind-2.9.7.jar;jackson-dataformat-xml-2.9.7.jar XML2JSON.java

Before you can run the resulting application, you'll need to download Woodstox, which is a high-performance XML processor that implements StAX, SAX2, and StAX2. I downloaded Woodstox 5.2.0. Then execute the following command (spread across three lines for readability) to run the application:

java -cp jackson-annotations-2.9.7.jar;jackson-core-2.9.7.jar;jackson-databind-2.9.7.jar; jackson-dataformat-xml-2.9.7.jar;stax2-api-3.1.3.jar;woodstox-core-5.2.0.jar;. XML2JSON

If all goes well, you should observe the following output:

{"name":"Earth","planet_from_sun":"3","moons":"1"}

Notice that the numbers assigned to the planet_from_sun and moons XML elements are serialized to JSON strings instead of numbers. The readTree() method doesn't infer the data type in the absence of an explicit type definition.

Jackson's support for XML tree traversal has additional limitations:

  • Jackson is unable to differentiate between objects and arrays. Because XML provides no means to differentiate an object from a list (array) of objects, Jackson collates repeated elements into a single value.
  • Jackson doesn't support mixed content (textual content and elements as children of an element). Instead, it maps each XML element to a JsonNode object. Any text is lost.

Given these limitations, it's not surprising that the official Jackson documentation recommends against parsing XML into JsonNode-based trees. You're better off using the data binding conversion technique.

Conclusion

Le matériel présenté dans cet article doit être considéré comme un addendum aux chapitres 6 et 11 de la deuxième édition de Java XML et JSON . En revanche, mon prochain article sera lié au livre mais entièrement nouveau. Gardez un œil sur mon prochain article sur la liaison d'objets Java à des documents JSON avec JSON-B.

Cette histoire, "Java XML et JSON: Traitement de documents pour Java SE, Partie 1: SAXON et Jackson" a été initialement publiée par JavaWorld.