Java XML dan JSON: Pemprosesan dokumen untuk Java SE, Bahagian 1: SAXON dan Jackson

Sebelumnya 1 2 Halaman 2 Halaman 2 dari 2

Transformasi

Sekarang mari kita cuba transformasi. Jalankan arahan berikut:

java XSLTDemo books.xml books.xsl

Malangnya, transformasi ini gagal: anda harus melihat output yang mengenal pasti Apache Xalan sebagai kilang pengubah dan mesej ralat yang menyatakan bahawa xsl:for-each-grouptidak disokong.

Mari cuba lagi. Dengan mengandaikannya saxon9he.jardan XSLTDemo.classberada di direktori semasa, jalankan perintah berikut:

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

Kali ini, anda harus memerhatikan output berikut yang disusun dan dikelompokkan dengan betul:

Tambahan Bab 11: Memproses JSON dengan Jackson

Menukar XML ke JSON dengan Jackson

Java XML dan JSON, Bab 11, memperkenalkan Jackson, yang menyediakan API untuk mengurai dan membuat objek JSON. Anda juga boleh menggunakan Jackson untuk menukar dokumen XML menjadi dokumen JSON.

Di bahagian ini, saya akan menunjukkan kepada anda dua cara untuk menukar XML ke JSON, pertama dengan pengikatan data dan kemudian dengan melintasi pokok. Saya akan menganggap bahawa anda telah membaca Bab 11 dan sudah biasa dengan Jackson. Untuk mengikuti demo ini, anda harus memuat turun fail JAR berikut dari repositori Maven:

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

Anda juga memerlukan beberapa fail JAR tambahan; kebanyakannya biasa untuk kedua-dua teknik penukaran. Saya akan memberikan maklumat mengenai mendapatkan fail JAR sebentar lagi.

Tukarkan XML ke JSON dengan pengikatan data

Pengikatan data membolehkan anda memetakan data bersiri ke objek Java. Sebagai contoh, andaikan anda mempunyai dokumen XML kecil yang menerangkan satu planet. Penyenaraian 4 membentangkan dokumen ini.

Penyenaraian 4. planet.xml

  Earth 3 9 

Penyenaraian 5 menyajikan Planetkelas Java yang setara yang objeknya memetakan planet.xmlkandungannya.

Penyenaraian 5. Planet.java

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

Proses penukaran menghendaki anda menguraikan XML terlebih dahulu ke dalam Planetobjek. Anda dapat menyelesaikan tugas ini dengan bekerja dengan com.fasterxml.jackson.dataformat.xml.XmlMapperkelas, seperti berikut:

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

XmlMapperadalah disesuaikan com.fasterxml.jackson.databind.ObjectMapperyang membaca dan menulis XML. Ini menyediakan beberapa readValue()kaedah untuk membaca satu nilai XML dari sumber input khusus XML; sebagai contoh:

 T readValue(XMLStreamReader r, Class valueType)

Setiap readValue()kaedah memerlukan javax.xml.stream.XMLStreamReaderobjek sebagai hujah pertama. Objek ini pada dasarnya adalah parser berasaskan aliran berasaskan StAX untuk menghuraikan teks dengan cekap ke hadapan.

Argumen kedua adalah java.lang.Classobjek untuk jenis target yang sedang dibuat, diisi dengan data XML, dan yang contohnya kemudian dikembalikan dari metode.

Intinya dari fragmen kod ini adalah bahawa kandungan Penyenaraian 4 dibaca menjadi Planetobjek yang readValue()kembali ke pemanggilnya.

Setelah objek dibuat, mudah untuk menulisnya sebagai JSON dengan bekerja ObjectMapperdan String writeValueAsString(Object value)kaedahnya:

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

Saya memetik fragmen kod ini dari XML2JSONaplikasi yang kod sumbernya lengkap muncul dalam Penyenaraian 6.

Penyenaraian 6. XML2JSON.java (Versi 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); } }

Sebelum anda dapat menyusun Senarai 5 dan 6, anda perlu memuat turun Jackson Dataformat XML, yang menggunakan XMLMapper. Saya memuat turun versi 2.9.7, yang sepadan dengan versi tiga pakej Jackson yang lain.

Dengan andaian bahawa anda berjaya memuat turun jackson-dataformat-xml-2.9.7.jar, laksanakan perintah berikut (tersebar di dua baris untuk dibaca) untuk menyusun kod sumber:

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

Sebelum anda dapat menjalankan aplikasi yang dihasilkan, anda perlu memuat turun Jackson Module: JAXB Annotations, dan juga memuat turun StAX 2 API. Saya memuat turun JAXB Annotations versi 2.9.7 dan StAX 2 API versi 3.1.3.

Dengan andaian bahawa anda berjaya memuat turun jackson-module-jaxb-annotations-2.9.7.jardan stax2-api-3.1.3.jar, jalankan arahan berikut (tersebar di tiga baris untuk dibaca) untuk menjalankan aplikasi:

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

Sekiranya semuanya berjalan lancar, anda harus memerhatikan output berikut:

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

Tukarkan XML ke JSON dengan melintasi pokok

Kaedah lain untuk menukar dari XML ke JSON adalah terlebih dahulu menguraikan XML menjadi pokok node JSON dan kemudian menuliskan pokok ini ke dokumen JSON. Anda boleh menyelesaikan tugas pertama dengan memanggil salah satu kaedah yang XMLMapperdiwarisi readTree():

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

ObjectMapper's JsonNode readTree(byte[] content)kaedah deserializes kandungan JSON menjadi pohon jackson.databind.JsonNodeobjek, dan pulangan akar JsonNodeobjek pokok ini. Dalam XmlMapperkonteks, kaedah ini mendeserialisasikan kandungan XML ke dalam pohon. Dalam kedua-dua kes, kandungan JSON atau XML diteruskan ke kaedah ini sebagai susunan bait.

Tugas kedua - menukar pokok objek menjadi JSON - dilaksanakan dengan cara yang serupa dengan yang saya tunjukkan sebelumnya. Kali ini, ia adalah JsonNodeobjek akar yang dihantar ke 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

Bahan yang disajikan dalam artikel ini harus dianggap sebagai tambahan pada Bab 6 dan 11 dalam edisi kedua Java XML dan JSON . Sebaliknya, artikel saya yang seterusnya akan berkaitan dengan buku tetapi bahan yang sama sekali baru. Awasi artikel saya yang akan datang mengenai mengikat objek Java ke dokumen JSON dengan JSON-B.

Kisah ini, "Java XML dan JSON: Pemprosesan dokumen untuk Java SE, Bahagian 1: SAXON dan Jackson" pada awalnya diterbitkan oleh JavaWorld.