Java XML и JSON: Обработка на документи за Java SE, Част 1: SAXON и Jackson

Предишна 1 2 Страница 2 Страница 2 от 2

Трансформация

Сега нека опитаме трансформацията. Изпълнете следната команда:

java XSLTDemo books.xml books.xsl

За съжаление, тази трансформация е неуспешна: трябва да наблюдавате изход, който идентифицира Apache Xalan като фабрика на трансформатори и съобщение за грешка, което посочва, че xsl:for-each-groupне се поддържа.

Нека опитаме отново. Ако приемем, че saxon9he.jarи XSLTDemo.classсе намират в текущата директория, изпълнете следната команда:

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

Този път трябва да наблюдавате следния сортиран и правилно групиран изход:

Допълнение към глава 11: Обработка на JSON с Джаксън

Преобразуване на XML в JSON с Джаксън

Java XML и JSON, Глава 11, въвеждат Jackson, който предоставя API за анализиране и създаване на JSON обекти. Също така е възможно да използвате Jackson за конвертиране на XML документи в JSON документи.

В този раздел ще ви покажа два начина за конвертиране на XML в JSON, първо с обвързване на данни и след това с обръщане на дърво. Предполагам, че сте прочели глава 11 и сте запознати с Джаксън. За да следвате тези демонстрации, трябва да изтеглите следните JAR файлове от хранилището на Maven:

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

Ще ви трябват и няколко допълнителни JAR файла; повечето са общи за двете техники за преобразуване. Скоро ще предоставя информация за получаването на тези JAR файлове.

Конвертирайте XML в JSON със свързване на данни

Обвързването на данни ви позволява да съпоставяте сериализирани данни с Java обект. Да предположим например, че имате малък XML документ, който описва една планета. Листинг 4 представя този документ.

Листинг 4. planet.xml

  Earth 3 9 

Листинг 5 представя еквивалентен Java Planetклас, чиито обекти съответстват planet.xmlна съдържанието на.

Листинг 5. Planet.java

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

Процесът на преобразуване изисква първо да анализирате XML в Planetобект. Можете да изпълните тази задача, като работите с com.fasterxml.jackson.dataformat.xml.XmlMapperкласа, както следва:

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

XmlMapperе персонализиран, com.fasterxml.jackson.databind.ObjectMapperкойто чете и пише XML. Той предоставя няколко readValue()метода за четене на една XML стойност от специфичен за XML източник на вход; например:

 T readValue(XMLStreamReader r, Class valueType)

Всеки readValue()метод изисква javax.xml.stream.XMLStreamReaderобект като първи аргумент. Този обект по същество е базиран на StAX базиран на потока анализатор за ефективно анализиране на текст по начин напред.

Вторият аргумент е java.lang.Classобект за целевия тип, който се екземпляри, попълва с XML данни и чийто екземпляр впоследствие се връща от метода.

Долният ред на този фрагмент от код е, че съдържанието на Листинг 4 се чете в Planetобект, който се readValue()връща към повикващия.

След като обектът е създаден, е лесно да го запишете като JSON, като работите с ObjectMapperнеговия String writeValueAsString(Object value)метод:

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

Аз извадих тези кодови фрагменти от XML2JSONприложение, чийто пълен изходен код се появява в листинг 6.

Листинг 6. XML2JSON.java (Версия 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); } }

Преди да можете да съставите списъци 5 и 6, ще трябва да изтеглите Jackson Dataformat XML, който изпълнява XMLMapper. Изтеглих версия 2.9.7, която съвпада с версиите на останалите три пакета Jackson.

Ако приемем, че сте изтеглили успешно jackson-dataformat-xml-2.9.7.jar, изпълнете следната команда (разпределена на два реда за четливост), за да компилирате изходния код:

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

Преди да можете да стартирате полученото приложение, ще трябва да изтеглите Jackson Module: JAXB Annotations, както и да изтеглите StAX 2 API. Изтеглих JAXB Annotations версия 2.9.7 и StAX 2 API версия 3.1.3.

Ако приемем, че сте изтеглили успешно jackson-module-jaxb-annotations-2.9.7.jarи stax2-api-3.1.3.jarизпълнете следната команда (разпределена в три реда за четливост), за да стартирате приложението:

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

Ако всичко върви добре, трябва да спазите следния изход:

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

Конвертирайте XML в JSON с обръщане на дърво

Друг начин за конвертиране от XML в JSON е първо да се анализира XML в дърво от JSON възли и след това да се запише това дърво в JSON документ. Можете да изпълните първата задача, като извикате един от XMLMapperнаследените readTree()методи на:

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

ObjectMapperе JsonNode readTree(byte[] content)метод deserializes съдържание JSON в дърво на jackson.databind.JsonNodeпредмети, и се връща в главната JsonNodeЦелта на това дърво. В XmlMapperконтекст този метод десериализира XML съдържание в дървото. И в двата случая съдържанието JSON или XML се предава на този метод като масив от байтове.

Втората задача - конвертиране на дървото на обектите в JSON - се изпълнява по подобен начин на това, което показах преди. Този път това е JsonNodeосновният обект, който се предава на 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

Представеният в тази статия материал трябва да се разглежда като допълнение към глави 6 и 11 във второто издание на Java XML и JSON . За разлика от това, следващата ми статия ще бъде свързана с книгата, но изцяло нов материал. Внимавайте за предстоящата ми статия за обвързването на Java обекти с JSON документи с JSON-B.

Тази история, „Java XML и JSON: Обработка на документи за Java SE, част 1: SAXON и Jackson“, първоначално е публикувана от JavaWorld.