Java XML und JSON: Dokumentverarbeitung für Java SE, Teil 1: SAXON und Jackson

Zurück 1 2 Page 2 Seite 2 von 2

Transformation

Versuchen wir nun die Transformation. Führen Sie den folgenden Befehl aus:

java XSLTDemo books.xml books.xsl

Leider schlägt diese Umwandlung fehl: Sie sollten eine Ausgabe beobachten, die Apache Xalan als Transformatorfabrik identifiziert, und eine Fehlermeldung, die besagt, dass dies xsl:for-each-groupnicht unterstützt wird.

Lass es uns erneut versuchen. Unter der Annahme , dass saxon9he.jarund XSLTDemo.classim aktuellen Verzeichnis befindet, führen Sie den folgenden Befehl ein :

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

Dieses Mal sollten Sie die folgende sortierte und richtig gruppierte Ausgabe beobachten:

Nachtrag zu Kapitel 11: Verarbeitung von JSON mit Jackson

Konvertieren von XML in JSON mit Jackson

In Java XML und JSON, Kapitel 11, wird Jackson vorgestellt, das APIs zum Parsen und Erstellen von JSON-Objekten bereitstellt. Es ist auch möglich, mit Jackson XML-Dokumente in JSON-Dokumente zu konvertieren.

In diesem Abschnitt werde ich Ihnen zwei Möglichkeiten zeigen, wie Sie XML in JSON konvertieren können, zuerst mit Datenbindung und dann mit Baumdurchquerung. Ich gehe davon aus, dass Sie Kapitel 11 gelesen haben und mit Jackson vertraut sind. Um diesen Demos zu folgen, sollten Sie die folgenden JAR-Dateien aus dem Maven-Repository heruntergeladen haben:

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

Sie benötigen außerdem einige zusätzliche JAR-Dateien. Die meisten sind beiden Konvertierungstechniken gemeinsam. Ich werde in Kürze Informationen zum Erhalt dieser JAR-Dateien bereitstellen.

Konvertieren Sie XML in JSON mit Datenbindung

Mit der Datenbindung können Sie serialisierte Daten einem Java-Objekt zuordnen. Angenommen, Sie haben ein kleines XML-Dokument, das einen einzelnen Planeten beschreibt. Listing 4 präsentiert dieses Dokument.

Listing 4. planet.xml

  Earth 3 9 

Listing 5 zeigt eine äquivalente Java- PlanetKlasse, deren Objekte dem planet.xmlInhalt zugeordnet sind.

Listing 5. Planet.java

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

Der Konvertierungsprozess erfordert, dass Sie zuerst das XML in ein PlanetObjekt analysieren . Sie können diese Aufgabe com.fasterxml.jackson.dataformat.xml.XmlMapperwie folgt ausführen, indem Sie mit der Klasse arbeiten:

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);

XmlMapperist eine benutzerdefinierte com.fasterxml.jackson.databind.ObjectMapper, die XML liest und schreibt. Es bietet verschiedene readValue()Methoden zum Lesen eines einzelnen XML-Werts aus einer XML-spezifischen Eingabequelle. zum Beispiel:

 T readValue(XMLStreamReader r, Class valueType)

Jede readValue()Methode benötigt ein javax.xml.stream.XMLStreamReaderObjekt als erstes Argument. Dieses Objekt ist im Wesentlichen ein StAX-basierter Stream-basierter Parser zum effizienten Parsen von Text in Vorwärtsrichtung.

Das zweite Argument ist ein java.lang.ClassObjekt für den Zieltyp, der instanziiert, mit XML-Daten gefüllt und dessen Instanz anschließend von der Methode zurückgegeben wird.

Die Quintessenz dieses Codefragments ist, dass der Inhalt von Listing 4 in ein PlanetObjekt eingelesen wird, readValue()das zu seinem Aufrufer zurückkehrt.

Sobald das Objekt erstellt wurde, ist es einfach, es als JSON zu schreiben, indem Sie mit ObjectMapperund seiner String writeValueAsString(Object value)Methode arbeiten:

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

Ich habe diese Codefragmente aus einer XML2JSONAnwendung extrahiert, deren vollständiger Quellcode in Listing 6 aufgeführt ist.

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); } }

Bevor Sie die Listings 5 ​​und 6 kompilieren können, müssen Sie das implementierte Jackson Dataformat XML herunterladen XMLMapper. Ich habe Version 2.9.7 heruntergeladen, die mit den Versionen der anderen drei Jackson-Pakete übereinstimmt.

Angenommen, Sie haben erfolgreich heruntergeladen jackson-dataformat-xml-2.9.7.jar, führen Sie den folgenden Befehl aus (zur besseren Lesbarkeit auf zwei Zeilen verteilt), um den Quellcode zu kompilieren:

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

Bevor Sie die resultierende Anwendung ausführen können, müssen Sie Jackson Module: JAXB Annotations und die StAX 2-API herunterladen. Ich habe JAXB Annotations Version 2.9.7 und StAX 2 API Version 3.1.3 heruntergeladen.

Angenommen, Sie haben erfolgreich heruntergeladen jackson-module-jaxb-annotations-2.9.7.jarund stax2-api-3.1.3.jarführen Sie den folgenden Befehl aus (zur besseren Lesbarkeit auf drei Zeilen verteilt), um die Anwendung auszuführen:

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

Wenn alles gut geht, sollten Sie die folgende Ausgabe beobachten:

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

Convert XML to JSON with tree traversal

Another way to convert from XML to JSON is to first parse the XML into a tree of JSON nodes and then write this tree to a JSON document. You can accomplish the first task by calling one of XMLMapper's inherited readTree() methods:

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

ObjectMapper's JsonNode readTree(byte[] content) method deserializes JSON content into a tree of jackson.databind.JsonNode objects, and returns the root JsonNode object of this tree. In an XmlMapper context, this method deserializes XML content into the tree. In either case, the JSON or XML content is passed to this method as an array of bytes.

The second task -- converting the tree of objects to JSON -- is accomplished in a similar manner to what I previously showed. This time, it's the JsonNode root object that's passed to 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

Das in diesem Artikel vorgestellte Material sollte als Ergänzung zu den Kapiteln 6 und 11 in der zweiten Ausgabe von Java XML und JSON betrachtet werden . Im Gegensatz dazu wird mein nächster Artikel sich auf das Buch beziehen, aber völlig neues Material. Halten Sie Ausschau nach meinem nächsten Artikel über das Binden von Java-Objekten an JSON-Dokumente mit JSON-B.

Diese Geschichte "Java XML und JSON: Dokumentverarbeitung für Java SE, Teil 1: SAXON und Jackson" wurde ursprünglich von JavaWorld veröffentlicht.