XML и JSON важны для меня, и я благодарен Apress за то, что они позволили мне написать о них книгу. в этомВопросы и ответы по JavaВ этой статье я кратко представлю второе издание моей новой книги,
. Я бы также предоставил две полезные демонстрации, которые я хотел бы включить в книгу, если бы у меня было место.Во-первых, я покажу вам, как переопределить Xalan, стандартную реализацию XSLT для Java 11, с альтернативами, совместимыми с XSLT 2.0+ и XPath 2.0+, в данном случаеSAXON. Доступ к таким функциям, как группировка, упрощается с помощью SAXON для XSLT/XPath, что я также продемонстрирую. Далее я покажу вам два способа преобразования XML в JSON с помощью Джексона: первый метод — привязка данных, а второй — обход дерева.
Почему стоит выбрать XML и JSON?
До появления XML я писал программы для импорта данных, хранящихся в недокументированном двоичном формате. Я использую отладчик для определения типа поля данных, смещения файла и длины. Эта технология значительно упростила мне жизнь, когда появился XML, а затем JSON.
В первом выпуске Java XML и JSON (июнь 2016 г.) были представлены XML и JSON, исследованы собственные API-интерфейсы Java SE, ориентированные на XML, и исследованы внешние API-интерфейсы, ориентированные на JSON, для Java SE. Недавно опубликовано Apressвторое изданиеПредлагает новый контент и (надеюсь) отвечает на дополнительные вопросы об XML, JSON, XML API Java SE и различных API JSON, включая JSON-P. Он также был обновлен для Java SE 11.
После написания этой книги я написал две отдельные части, в которых представил полезные функции SAXON и Jackson. Я расскажу об этих частях в этой статье. Во-первых, я воспользуюсь моментом, чтобы представить книгу и ее содержание.
Java XML и JSON, второе издание
В идеале, вы должны прочитать второе издание, прежде чем изучать остальную часть этой статьи.
Второе издание Java XML и JSON разделено на три части, состоящие из 12 глав и приложений:
- Часть 1. Изучение XML
- Глава 1: Введение в XML
- Глава 2: Анализ XML-документов с помощью SAX
- Глава 3: Разбор и создание XML-документов с помощью DOM
- Глава 4: Анализ и создание XML-документов с помощью StAX
- Глава 5: Выбор узлов с помощью XPath
- Глава 6: Преобразование XML-документов с помощью XSLT
- Часть 2. Изучение JSON
- Глава 7: Введение в JSON
- Глава 8: Анализ и создание объектов JSON с помощью mJson
- Глава 9: Анализ и создание объектов JSON с помощью Gson
- Глава 10: Извлечение значений JSON с помощью JsonPath
- Глава 11: Обработка JSON с помощью Jackson Глава 12: Обработка JSON с помощью JSON-P
- Часть 3: Приложение Приложение A: Ответы на упражнения
Часть 1 посвящена XML. Глава 1 определяет ключевые термины, вводит особенности языка XML (объявления XML, элементы и атрибуты, ссылки на символы и разделы CDATA, пространства имен, комментарии и директивы обработки) и знакомит с проверкой XML-документов (посредством определений типов документов и схем). В оставшихся пяти главах рассматриваются API-интерфейсы SAX, DOM, StAX, XPath и XSLT Java SE.
Часть 1 посвящена XML. Глава 1 определяет ключевые термины, вводит особенности языка XML (объявления XML, элементы и атрибуты, ссылки на символы и разделы CDATA, пространства имен, комментарии и директивы обработки) и знакомит с проверкой XML-документов (посредством определений типов документов и схем). В оставшихся пяти главах рассматриваются API-интерфейсы SAX, DOM, StAX, XPath и XSLT Java SE.
Часть 2 посвящена JSON. Глава 7 определяет ключевые термины, исследует синтаксис JSON, демонстрирует JSON в контексте JavaScript (поскольку JSON еще официально не поддерживается Java SE) и показывает, как проверять объекты JSON (с помощью онлайн-инструмента JSON Schema Validator). В оставшихся пяти главах рассматриваются сторонние API mJSon, Gson, JsonPath и Jackson, а также JSON-P API Oracle для Java EE, который также можно неофициально использовать в контексте Java SE.
Каждая глава заканчивается серией упражнений, включая упражнения по программированию, предназначенные для закрепления понимания материала читателем. Ответы опубликованы в приложении к книге.
Новая версия отличается от своей предшественницы несколькими важными моментами:
- Глава 2 описывает правильный способ получения средства чтения XML. Метод из предыдущей версии устарел.
- Глава 3 также охватывает загрузку и сохранение DOM, область действия и API-интерфейсы обхода.
- Глава 6 описывает, как использовать SAXON для выхода за рамки XSLT/XPath 1.0.
- Глава 11 — это новая (и длинная) глава, посвященная Джексону.
- Глава 12 — это новая (и длинная) глава, посвященная JSON-P.
В этом выпуске также исправлены мелкие ошибки в содержании предыдущего издания, обновлены различные рисунки и добавлено множество новых упражнений.
Хотя у меня нет места во втором издании,
Глава 6 Приложение: Преобразование XML-документов с помощью XSLT
Помимо XSLT/XPath 1.0 с SAXON
Реализация XSLT в Java 11 основана наApache Xalan Project, который поддерживает XSLT 1.0 и XPath 1.0, но только более ранние версии. Чтобы получить доступ к будущим функциям XSLT 2.0+ и XPath 2.0+, вам нужно использоватьSAXONальтернативы переопределяют реализацию Xalan.
Java XML и JSON, Глава 6 ВведениеУзнайте, как переопределить Xalan с помощью SAXON, а затем убедитесь, что SAXON используется. В демонстрации я предлагаю, чтобы в приложенииmain()
Вставьте следующую строку в начале метода, чтобы использовать SAXON:
System.setProperty("javax.xml.transform.TransformerFactory",
"net.sf.saxon.TransformerFactoryImpl");
На самом деле вам не нужен вызов этого метода, потому что SAXONTransformerFactory
Реализация предоставляется как служба в файле JAR, который автоматически загружается при доступе к файлу JAR через путь к классам. но еслиTransformerFactory
Может возникнуть проблема с несколькими файлами реализации JAR в пути к классам и средой выполнения Java, выбирающей службу, отличную от SAXON, в качестве реализации преобразователя. Включение вышеуказанного вызова метода переопределит выбор SAXON.
Функциональность XSLT/XPath: демонстрация
Глава 6 знакомит с двумяXSLTDemo
приложение, третье приложение можно найти в архиве кода этой книги. В листинге 1 ниже представлен четвертыйXSLTDemo
Демонстрационное приложение, демонстрирующее возможности XSLT/XPath.
Листинг 1. XSLTDemo.java
import java.io.FileReader;
import java.io.IOException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;
import static java.lang.System.*;
public class XSLTDemo
{
public static void main(String[] args)
{
if (args.length != 2)
{
err.println("usage: java XSLTDemo xmlfile xslfile");
return;
}
try
{
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(args[0]);
TransformerFactory tf = TransformerFactory.newInstance();
out.printf("TransformerFactory: %s%n", tf);
FileReader fr = new FileReader(args[1]);
StreamSource ssStyleSheet = new StreamSource(fr);
Transformer t = tf.newTransformer(ssStyleSheet);
Source source = new DOMSource(doc);
Result result = new StreamResult(out);
t.transform(source, result);
}
catch (IOException ioe)
{
err.printf("IOE: %s%n", ioe.toString());
}
catch (FactoryConfigurationError fce)
{
err.printf("FCE: %s%n", fce.toString());
}
catch (ParserConfigurationException pce)
{
err.printf("PCE: %s%n", pce.toString());
}
catch (SAXException saxe)
{
err.printf("SAXE: %s%n", saxe.toString());
}
catch (TransformerConfigurationException tce)
{
err.printf("TCE: %s%n", tce.toString());
}
catch (TransformerException te)
{
err.printf("TE: %s%n", te.toString());
}
catch (TransformerFactoryConfigurationError tfce)
{
err.printf("TFCE: %s%n", tfce.toString());
}
}
}
Код в листинге 1 похож на код в листинге 6-2 в главе 6, но есть некоторые отличия. первый,main()
Метод в листинге 1 должен вызываться с двумя аргументами командной строки: первый аргумент именует XML-файл, второй аргумент — имя XSL-файла.
Второе отличие состоит в том, что я не устанавливал никаких выходных свойств преобразователя. В частности, я не указал метод вывода или использовать ли отступ. Эти задачи можно выполнить в файлах XSL.
Скомпилируйте листинг 1 следующим образом:
javac XSLTDemo.java
Пример XSLT 2.0: группировка узлов
XSLT 1.0 не предоставляет встроенной поддержки для группировки узлов. Например, вы можете преобразовать следующий XML-документ, в котором перечислены книги автора:
<book title="Book 1">
<author name="Author 1" />
<author name="Author 2" />
</book>
<book title="Book 2">
<author name="Author 1" />
</book>
<book title="Book 3">
<author name="Author 2" />
<author name="Author 3" />
</book>
Введите следующий XML-код со списком книг автора:
<author name="Author 1">
<book title="Book 1" />
<book title="Book 2" />
</author>
<author name="Author 2">
<book title="Book 1" />
<book title="Book 3" />
</author>
<author name="Author 3">
<book title="Book 3" />
</author>
Хотя это преобразование возможно в XSLT 1.0, оно неудобно.xsl:for-each-group
Напротив, элементы XSLT 2.0 позволяют взять набор узлов, сгруппировать их по некоторым критериям и обработать каждую созданную группу.
Давайте рассмотрим эту функцию, начиная с XML-документа, который необходимо обработать. Листинг 2 показываетbooks.xml
Содержимое файлов сгруппировано по именам авторов по названию.
Листинг 2. books.xml (сгруппированы по названию)
<?xml version="1.0"?>
<books>
<book title="Securing Office 365: Masterminding MDM and Compliance in the Cloud">
<author name="Matthew Katzer"/>
<publisher name="Apress" isbn="978-1484242292" pubyear="2019"/>
</book>
<book title="Office 2019 For Dummies">
<author name="Wallace Wang"/>
<publisher name="For Dummies" isbn="978-1119513988" pubyear="2018"/>
</book>
<book title="Office 365: Migrating and Managing Your Business in the Cloud">
<author name="Matthew Katzer"/>
<author name="Don Crawford"/>
<publisher name="Apress" isbn="978-1430265269" pubyear="2014"/>
</book>
</books>
В листинге 3 показанbooks.xsl
Содержимое файла, которое обеспечивает преобразование XSL, преобразующее этот документ в документ, в котором названия книг сгруппированы в соответствии с именами авторов.
Листинг 3. books.xsl (сгруппированы по именам авторов)
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
<xsl:output method="html" indent="yes"/>
<xsl:template match="/books">
<html>
<head>
</head>
<body>
<xsl:for-each-group select="book/author" group-by="@name">
<xsl:sort select="@name"/>
<author name="{@name}">
<xsl:for-each select="current-group()">
<xsl:sort select="../@title"/>
<book title="{../@title}" />
</xsl:for-each>
</author>
</xsl:for-each-group>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Долженxsl:output
Элемент представляет собой вывод HTML, который должен иметь отступ. изxsl:template-match
Однофазное согласование компонентовbooks
корневой элемент. Долженxsl:for-each-group
Элемент выбирает ряд узлов и объединяет их в группы. Долженselect
Атрибут — это выражение XPath, которое идентифицирует элемент для группировки. Здесь сказано выбратьauthor
принадлежатьbook
Все элементы элемента. Долженgroup-by
Атрибут группирует все элементы с одинаковым значением, ключ группировки оказывается элементом@name
Атрибутыauthor
. По сути, вы получите следующие группы:
Group 1
Matthew Katzer
Matthew Katzer
Group 2
Wallace Wang
Group 3
Don Crawford
Эти группы расположены не в алфавитном порядке имен авторов, поэтомуauthor
выведет элемент, которыйMatthew Katzer
первыйDon Crawford
Тоже последний. Долженxsl:sort select="@name"
элемент обеспечиваетauthor
Элементы выводятся в отсортированном порядке.
Должен<author name="{@name}">
построить вывод a<author>
ярлык, егоname
Атрибуты назначаются только первому имени автора в группе.
Продолжать,xsl:for-each select="current-group()"
повторять текущийfor-each-group
Имена авторов в группе итераций. Долженxsl:sort select="../@title"
Конструкция будет сочетаться сbook
последующая деятельность<book title="{../@title}" />
Создает указанные выходные элементы для сортировки
Transformation
Теперь давайте попробуем трансформацию. Выполните следующую команду:
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
На этот раз вы должны наблюдать следующий отсортированный и правильно сгруппированный вывод:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<author name="Don Crawford">
<book title="Office 365: Migrating and Managing Your Business in the Cloud"></book>
</author>
<author name="Matthew Katzer">
<book title="Office 365: Migrating and Managing Your Business in the Cloud"></book>
<book title="Securing Office 365: Masterminding MDM and Compliance in the Cloud"></book>
</author>
<author name="Wallace Wang">
<book title="Office 2019 For Dummies"></book>
</author>
</body>
</html>
Глава 11 Приложение: Работа с JSON с Джексоном
Конвертируйте XML в JSON с Джексоном
Java XML и JSON, глава 11Представлен Jackson, который предоставляет API для анализа и создания объектов JSON. Также можно преобразовать XML-документы в документы JSON с помощью Jackson.
В этом разделе я покажу вам два способа преобразования XML в JSON, сначала с привязкой данных, а затем с обходом дерева. Я предполагаю, что вы прочитали главу 11 и знакомы с Джексоном. Чтобы следовать этим демонстрациям, вы должны начать сРепозиторий MavenЗагрузите следующие JAR-файлы:
jackson-annotations-2.9.7.jar
jackson-core-2.9.7.jar
jackson-databind-2.9.7.jar
Вам также понадобятся некоторые дополнительные файлы JAR, общие для большинства методов преобразования. Я предоставлю информацию о получении этих файлов JAR как можно скорее.
Преобразование XML в JSON с помощью привязки данных
Листинг 4. Planet.xml
<?xml version="1.0" encoding="UTF-8"?>
<planet>
<name>Earth</name>
<planet_from_sun>3</planet_from_sun>
<moons>9</moons>
</planet>
В листинге 5 показан эквивалентный JavaPlanet
класс, объекты которого отображаются на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> T readValue(XMLStreamReader r, Class<T> valueType)
каждыйreadValue()
метод требуетjavax.xml.stream.XMLStreamReader
объект в качестве первого аргумента. Этот объект, по сути, представляет собой потоковый синтаксический анализатор на основе StAX для эффективного синтаксического анализа текста в прямом направлении.
Второй параметрjava.lang.Class
Создаваемый объект целевого типа, заполняемый XML-данными, и его экземпляр, возвращаемый этим методом.
Суть этого фрагмента в том, что содержимое листинга 4 считывается в ответ вызывающей стороне.Planet
объектreadValue()
.
После того, как объект создан, к нему можно получить доступ с помощьюObjectMapper
этоString writeValueAsString(Object value)
способ записать его как JSON:
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, вам необходимо скачатьДжексон ДАННЫЕ ФОРМАТ 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
Перед запуском сгенерированного приложения необходимо скачатьМодуль Джексона: аннотации JAXB, и скачать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)
метод для десериализации содержимого JSON вjackson.databind.JsonNode
дерево объектов и возвратJsonNode
Корневой объект для этого дерева. существуетXmlMapper
В контексте этот метод десериализует содержимое XML в дерево. В любом случае содержимое JSON или XML передается этому методу в виде массива байтов.
Вторая задача — преобразование дерева объектов в JSON — выполняется аналогично тому, что я показывал ранее. На этот раз этоJsonNode
является корневым объектом, переданнымwriteValueAsString()
:
ObjectMapper jsonMapper = new ObjectMapper();
String json = jsonMapper.writeValueAsString(node);
я изXML2JSON
Полный исходный код взят из приложения, показанного в листинге 7, с этими фрагментами кода.
Листинг 7. XML2JSON.java (версия 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 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+
"<planet>\n" +
" <name>Earth</name>\n" +
" <planet_from_sun>3</planet_from_sun>\n" +
" <moons>1</moons>\n" +
"</planet>\n";
XmlMapper xmlMapper = new XmlMapper();
JsonNode node = xmlMapper.readTree(xml.getBytes());
ObjectMapper jsonMapper = new ObjectMapper();
String json = jsonMapper.writeValueAsString(node);
out.println(json);
}
}
Выполните следующую команду (разделенную на две строки для удобства чтения), чтобы скомпилировать листинг 7:
javac -cp jackson-core-2.9.7.jar;jackson-databind-2.9.7.jar;jackson-dataformat-xml-2.9.7.jar
XML2JSON.java
Перед запуском сгенерированного приложения необходимо скачатьWoodstox, который представляет собой высокопроизводительный XML-процессор, реализующий StAX, SAX2 и StAX2. Я скачал Woodstox 5.2.0. Затем выполните следующие команды (распределенные на три строки для удобочитаемости), чтобы запустить приложение:
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
Если все пойдет хорошо, вы должны увидеть следующий вывод:
{"name":"Earth","planet_from_sun":"3","moons":"1"}
Обратите внимание, что присваивание элементам XMLplanet_from_sun
а такжеmoons
Номера элементов XML сериализуются как строки JSON, а не числа.readTree()
При отсутствии явного определения типа метод не выводит тип данных.
Поддержка Джексоном обхода XML-дерева имеет дополнительные ограничения:
- Джексон не может различать объекты и массивы. Поскольку XML не может отличать объекты от списков (массивов) объектов, Джексон организует повторяющиеся элементы в одно значение.
- Джексон не поддерживает смешанный контент (текстовый контент и элементы как дочерние элементы). Вместо этого он сопоставляет каждый элемент XML с
JsonNode
объект. Любой текст будет потерян.
Учитывая эти ограничения,Официальная документация ДжексонаНе рекомендуется анализировать XML, т.к.JsonNode
Древовидная структура неудивительна. Вам лучше использовать методы преобразования привязки данных.
В заключение
Материал, представленный в этой статье, следует рассматривать как приложение к главам 6 и 11 второго издания Java XML и JSON. Напротив, моя следующая статья будет о книге, но с совершенно новым материалом. Пожалуйста, следуйте моему следующему сообщению о привязке объектов Java к документам JSON с использованием JSON-B.
Английский оригинал:Woohoo. Java world.com/article/334…
Общедоступный номер: Galaxy № 1
Контактный адрес электронной почты: public@space-explore.com
(Пожалуйста, не перепечатывайте без разрешения)