Конвертировать JSON в XML Java с использованием Gson и JAXB

⚡ Умное резюме

Конвертировать JSON в XML Java с использованием Gson и JAXB по картеping оба формата на одной и той же аннотированной странице Java классы. В этой статье определен каждый формат, настроен проект, выполнена десериализация XML с помощью JAXB, записан JSON с помощью Gson, а также описан обратный процесс.

  • 🗝️ Структура JSON: Данные хранятся в виде пар ключ-значение внутри фигурных скобок, при этом каждая запись разделена запятыми.
  • 🏷️ XML-структура: Данные хранятся во вложенных узлах, где каждый открывающий тег требует соответствующего закрывающего тега.
  • 🔗 Общая модель: Один набор аннотированных Java Классы выступают в качестве связующего звена, поэтому ни один формат не преобразуется напрямую в другой.
  • 📥 Демаршаллинг: JAXB считывает XML-файл и возвращает заполненный объект. Java Дерево объектов через класс Unmarshaller.
  • 📤 Потоковая запись: Гсон ДжсонWriter генерирует JSON-данные постепенно, используя вызовы beginObject, name, value и endObject.
  • 🔄 Reverse Путь: JsonReader восстанавливает объекты из JSON, а JAXB Marshaller записывает их обратно в формате XML.
  • ⚠️ Примечание во время выполнения: JAXB оставил JDK на Java 11, поэтому зависимость jakarta.xml.bind необходимо добавить явно.

Преобразование JSON в XML Java

Что такое JSON?

JSON — это аббревиатура для JavaФормат Script Object Notation (JSON) — это формат данных, который подчиняется правилам, понятным большинству языков программирования. Мы можем легко сохранить его в файл или в базу данных. Формат JSON использует пары ключ-значение для описания данных.

В следующем примере мы определяем строку JSON, которая хранит персональную информацию:

{
"username" : "guru99user",
"email" : "guru99user@mail.com"
}

Таким образом, синтаксис JSON очень прост. Каждый элемент данных состоит из двух частей: ключа и значения, которые соответствуют имени поля и его значению в записи. Если посмотреть дальше, можно выделить несколько подобных правил:

  • Строка JSON заключена в фигурные скобки {}.
  • Ключи JSON-данных должны быть заключены в двойные кавычки, а строковые значения также должны быть заключены в кавычки.
  • Если данных больше (больше пар ключ => значение), мы используем запятые (,) для их разделения.
  • В качестве ключей JSON следует использовать обычные буквы, цифры или символ подчеркивания, без пробелов, при этом первый символ не должен быть цифрой.

Что такое XML?

XML расшифровывается как eXtensible Markup Language (расширяемый язык разметки), предложенный Консорциумом Всемирной паутины (World Wide Web Consortium).https://www.w3.org/) для создания других языков разметки. Это простое подмножество, которое может описывать множество различных типов данных, поэтому оно очень полезно для обмена данными между системами.

Теги в XML часто не определены заранее, а создаются в соответствии с пользовательскими соглашениями. XML представляет новые функции, основанные на преимуществах HTML.

В XML-файлах есть ряд полезных функций для различных систем и решений:

  • XML расширяем: XML позволяет вам создавать собственные теги, соответствующие вашему приложению.
  • XML хранит данные, но не отображает их: XML позволяет хранить данные независимо от способа их отображения.
  • XML является общим стандартом: XML был разработан Консорциумом Всемирной паутины (W3C) и доступен как открытый стандарт.

XML построен на основе вложенной узловой структуры. Каждый узел имеет открывающий и закрывающий теги следующим образом:

<node>content</node>

В котором:

  • Это открытый тег, и имя этого тега определяется вами.
  • Это закрывающий тег, и имя этого тега должно совпадать с именем открывающего тега.
  • содержание — это содержимое этого тега.

В верхней части каждого XML-файла необходимо объявить тег, указывающий используемую версию XML. Синтаксис тега инструкции:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

JSON против XML: ключевые различия

Оба формата содержат структурированные данные, и в таблице ниже показано, почему проекту может потребоваться переключаться между ними.

Параметр JSON XML
Синтаксический стиль Пары ключ-значение Вложенные теги
Типы данных Строка, число, логическое значение, null, массив, объект Только текст, типы данных берутся из схемы.
Атрибуты Не поддерживается Поддерживается на любом элементе
Комментарии Не поддерживается Поддержанный
многословие Компактный Более многословно, потому что теги повторяются.
Проверка схемы Схема JSON, необязательно DTD и XSD, зрелые
Типичное использование Веб-API и конфигурация Корпоративная система обмена сообщениями и документами

Что такое Гсон?

Гсон (https://github.com/google/gson) Является Java библиотека, которая позволяет пользователям конвертировать Java объект в строку JSON, а также для преобразования строки JSON обратно в Java объект. Gson может работать с произвольными Java объекты, включая существующие объекты, исходный код которых у вас отсутствует.

Начиная с версии 1.6, Gson вводит два класса: JsonReader и JsonWriterдля обеспечения потоковой обработки данных в формате JSON.

  • JsonWriter – Потоковая запись в JSON. Мы создаём JsonWriter Для начала и завершения создания JSON-объекта мы используем функции. начатьОбъект() и КонечныйОбъект()Между этими двумя вызовами мы записываем данные в виде пар (ключ => значение).
JsonWriter writer = new JsonWriter();
writer.beginObject();
writer.name("key").value("value");
writer.endObject();
  • JsonReader – Потоковое чтение из JSON. Мы создаём объект JsonReader. Для начала и завершения чтения объекта JSON мы используем функции beginObject() и endObject(). Между этими двумя вызовами мы считываем данные парами (ключ => значение).
JsonReader reader = new JsonReader();
reader.beginObject();
while (reader.hasNext()) {
	String name = reader.nextName();
	if (name.equals("key")) {
		String value = reader.nextString();
	}
}
reader.endObject();

Обработка потоковых данных в Gson выполняется быстро. Однако вам необходимо самостоятельно обрабатывать каждую пару (ключ => значение) данных JSON.

Что такое JAXB?

JAXB означает Java Archiтектура для XML Binding, которая представляет собой библиотеку, использующую аннотации для преобразования Java Преобразование объектов в XML-контент и наоборот. Поскольку JAXB определяется спецификацией, мы можем использовать различные реализации этого стандарта.

В JAXB мы часто используем следующие основные аннотации:

  • @XmlRootElementЭта аннотация указывает на самый внешний тег XML-файла и, следовательно, объявляется выше класса.
  • @XmlElementWrapper: эта аннотация создает элемент XML-обертки вокруг коллекций.
  • @XmlElementЭта аннотация указывает, что свойство объекта становится дочерним тегом XML-файла.
  • @XmlАтрибутЭта аннотация указывает, что свойство объекта становится атрибутом окружающего тега.

Общая реализация выглядит следующим образом. Сначала мы инициализируем JAXBContext объект с МойОбъект класс для преобразования.

JAXBContext jaxbContext = JAXBContext.newInstance(MyObject.class);

Эта JAXBContext У объекта есть метод, который создает объект, преобразующий XML-содержимое в... Java объект, Демаршаллер.

Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();

Такой же JAXBContext У объекта также есть метод, который создает объект, преобразующий Java объект в XML-содержимое, Маршаллер.

Marshaller marshallerObj = jaxbContext.createMarshaller();

⚠️ Предупреждение: JAXB был удален из JDK в Java 11. На Java В версиях 11 и выше API и реализация среды выполнения добавляются в проект явно, например: jakarta.xml.bind:jakarta.xml.bind-api вместе с org.glassfish.jaxb:jaxb-runtimeи импортировать аннотации из jakarta.xml.bind.annotation вместо javax.xml.bind.annotation.

Как конвертировать XML в JSON?

Мы реализовали пример преобразования XML в JSON на следующей платформе. Указанные ниже версии использовались для скриншотов. Более новые версии JDK, EclipseGson и Gson работают аналогичным образом, с учетом примечания JAXB, приведенного выше.

  • OpenJDK 8 для Ubuntu 18.04 x64.
  • Eclipse IDE 2019-03 (4.11.0) x64 Java Разработка для Ubuntu.
  • Гсон 2.8.5.

Шаг 1) Создать проект.
Создать новый Java проект.

Создать новый Java Проект.

Шаг 2) Укажите название проекта.
Задайте название проекта. XmlToJsonExample.

Установить имя проекта

Шаг 3) Создайте папку.
Создайте папку ввод данных содержащий два файла образец.xml и образец.json.

Создать данные папки

Давайте сначала определим наш XML-файл с помощью отдел, роль и человека свойства.

Общая архитектура такова: один отдел выполняет множество ролей, а одна роль обслуживается множеством людей. На диаграмме ниже показаны эти взаимосвязи.

Объектные отношения

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root>
	<department>
		<roles>
			<role id="1">
				<position>head</position>
				<salary>10k</salary>
			</role>
			<role id="2">
				<position>manager</position>
				<salary>8k</salary>
			</role>
			<role id="3">
				<position>employee</position>
				<salary>5k</salary>
			</role>
		</roles>
		<persons>
			<person id="1">
				<name>Red</name>
				<role>1</role>
			</person>
			<person id="2">
				<name>Green</name>
				<role>2</role>
			</person>
			<person id="3">
				<name>Blue</name>
				<role>2</role>
			</person>
			<person id="4">
				<name>Yellow</name>
				<role>3</role>
			</person>
			<person id="5">
				<name>Brown</name>
				<role>3</role>
			</person>
		</persons>
	</department>
</root>

Во-вторых, мы определяем JSON, выражающий ту же идею. Обратите внимание, что плоский список людей становится вложенным массивом внутри каждой роли, что в точности соответствует преобразованию, выполняемому кодом конвертации.

{
	"roles": [
		{
			"id": "1",
			"position": "head",
			"salary": "10k",
			"persons": [
				{
					"id": "1",
					"name": "Red"
				}
			]
		},
		{
			"id": "2",
			"position": "manager",
			"salary": "8k",
			"persons": [
				{
					"id": "2",
					"name": "Green"
				},
				{
					"id": "3",
					"name": "Blue"
				}
			]
		},
		{
			"id": "3",
			"position": "employee",
			"salary": "5k",
			"persons": [
				{
					"id": "4",
					"name": "Yellow"
				},
				{
					"id": "5",
					"name": "Brown"
				}
			]
		}
	]
}

Шаг 4) Определите объекты.
Определите соответствующие классы объектов в пакете. модели.

Определить классы объектов

Role.java

@XmlRootElement(name = "role")
public class Role {
	private String id;
	private String position;
	private String salary;
	public Role() {
		super();
	}
	public Role(String id, String position, String salary) {
		super();
		this.id = id;
		this.position = position;
		this.salary = salary;
	}
	@XmlAttribute(name = "id")
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	@XmlElement(name = "position")
	public String getPosition() {
		return position;
	}
	public void setPosition(String position) {
		this.position = position;
	}
	@XmlElement(name = "salary")
	public String getSalary() {
		return salary;
	}
	public void setSalary(String salary) {
		this.salary = salary;
	}
}

Человек.java

@XmlRootElement(name = "person")
public class Person {
	private String id;
	private String name;
	private String role;
	public Person() {
		super();
	}
	public Person(String id, String name, String role) {
		super();
		this.id = id;
		this.name = name;
		this.role = role;
	}
	@XmlAttribute(name = "id")
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	@XmlElement(name = "name")
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
	@XmlElement(name = "role")
	public String getRole() {
		return role;
	}
	public void setRole(String role) {
		this.role = role;
	}
}

Department.java

@XmlRootElement(name = "department")
public class Department {
	private List<Role> roles;
	private List<Person> persons;
	public Department() {
		super();
	}
	public Department(List<Role> roles, List<Person> persons) {
		super();
		this.roles = roles;
		this.persons = persons;
	}
	@XmlElementWrapper(name = "roles")
	@XmlElement(name = "role")
	public List<Role> getRoles() {
		return roles;
	}
	public void setRoles(List<Role> roles) {
		this.roles = roles;
	}
	@XmlElementWrapper(name = "persons")
	@XmlElement(name = "person")
	public List<Person> getPersons() {
		return persons;
	}
	public void setPersons(List<Person> persons) {
		this.persons = persons;
	}
}

XMLModel.java

@XmlRootElement(name = "root")
public class XMLModel {

	private Department department;

	public XMLModel() {
		super();
	}

	public XMLModel(Department department) {
		super();
		this.department = department;
	}

	@XmlElement(name = "department")
	public Department getDepartment() {
		return department;
	}

	public void setDepartment(Department department) {
		this.department = department;
	}

}

Шаг 5) Настройте библиотеку.
Добавьте и настройте библиотеку Gson 2.8.5 в Java Путь сборки.

Настроить библиотеку Gson

Добавьте библиотеку Gson 2.8.5 в Java Путь сборки

Если проект использует Специалист Вместо вручную добавленного JAR-файла, те же библиотеки объявлены как зависимости. Версия 2.8.5 зафиксирована здесь в соответствии со скриншотами, и любая более поздняя версия Gson работает идентично для этого примера:

<dependencies>
    <dependency>
        <groupId>com.google.code.gson</groupId>
        <artifactId>gson</artifactId>
        <version>2.8.5</version>
    </dependency>

    <!-- required on Java 11 and later -->
    <dependency>
        <groupId>jakarta.xml.bind</groupId>
        <artifactId>jakarta.xml.bind-api</artifactId>
    </dependency>
    <dependency>
        <groupId>org.glassfish.jaxb</groupId>
        <artifactId>jaxb-runtime</artifactId>
    </dependency>
</dependencies>

Преобразование XML-сообщения в Java объекты с использованием JAXB

Во-первых, мы определяем классы, выполняющие функции, в этом пакете. СЕРВИС.

Определить исполнительские классы

На первом этапе первого процесса мы используем технику демаршаллинга JAXB.

Десериализация предоставляет клиентскому приложению возможность преобразовывать XML-данные в формат, производный от JAXB. Java объекты.

Определим функцию getObjectFromXmlFile чтобы десериализовать наш XML-файл обратно в Java объект. Эта функция определена в классе. XMLService.

public XMLModel getObjectFromXmlFile(String filePath) {
	try {
		File file = new File(filePath);
		JAXBContext jaxbContext = JAXBContext.newInstance(XMLModel.class);

		Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
		XMLModel root = (XMLModel) jaxbUnmarshaller.unmarshal(file);

		return root;
	} catch (JAXBException e) {
		e.printStackTrace();
		return null;
	}
}

Мы вызываем приведенный выше код внутри класса. XmlToJsonService.

XMLService xmlService = new XMLService();
XMLModel xmlModel = xmlService.getObjectFromXmlFile(filePathIn);

Department department = xmlModel.getDepartment();
List<Role> roles = department.getRoles();
List<Person> persons = department.getPersons();

На этом этапе XML-файл стал состоять из трех частей. Java Объекты находятся в памяти. На следующем шаге они записываются в формате JSON.

Конвертировать Java объекты для сообщения JSON с использованием Gson

На этом этапе мы определяем функцию. записьдататоджсонфиле Для записи данных в JSON-файл. Эта функция определена в классе. JsonService.

Обратите внимание, что для записи списка объектов JSON мы используем функции. начатьArray() и КонецArray()Между этими двумя вызовами мы записываем каждый JSON-объект.

public void writeDataToJsonFile(String filePath, List<Role> roles, List<Person> persons) {
	try {
		JsonWriter writer = new JsonWriter(new FileWriter(filePath));
		writer.setIndent("    ");
		writer.beginObject();
		writer.name("roles");
		writer.beginArray();
		for (Role role : roles) {
			writer.beginObject();
			writer.name("id").value(role.getId());
			writer.name("position").value(role.getPosition());
			writer.name("salary").value(role.getSalary());
			writer.name("persons");
			writer.beginArray();
			for (Person person : persons) {
				if (person.getRole().equalsIgnoreCase(role.getId())) {
					writer.beginObject();
					writer.name("id").value(person.getId());
					writer.name("name").value(person.getName());
					writer.endObject();
				}
			}
			writer.endArray();
			writer.endObject();
		}
		writer.endArray();
		writer.endObject();
		writer.close();
	} catch (IOException e) {
	}
}

Мы вызываем приведенный выше код в классе. XmlToJsonService.

JsonService jsonService = new JsonService();
jsonService.writeDataToJsonFile(filePathOut, roles, persons);

Это первый этап. Внутренний цикл сопоставляет каждого человека с текущим идентификатором роли, благодаря чему плоский XML-список людей превращается во вложенный JSON-массив.

Преобразовать сообщение JSON в Java объекты с использованием Gson

На первом этапе второго процесса мы определяем функцию. getDataFromJsonFile Для чтения данных из JSON-файла. Эта функция определена в классе. JsonService.

Обратите внимание, что для чтения списка объектов JSON мы используем функции. начатьArray() и КонецArray()Между этими двумя вызовами мы считываем каждый JSON-объект.

public void getDataFromJsonFile(String filePath, List<Role> roles, List<Person> persons) {
	try {
		JsonReader reader = new JsonReader(new FileReader(filePath));
		reader.beginObject();
		while (reader.hasNext()) {
			String nameRoot = reader.nextName();
			if (nameRoot.equals("roles")) {
				reader.beginArray();
				while (reader.hasNext()) {
					reader.beginObject();
					Role role = new Role();
					while (reader.hasNext()) {
						String nameRole = reader.nextName();
						if (nameRole.equals("id")) {
							role.setId(reader.nextString());
						} else if (nameRole.equals("position")) {
							role.setPosition(reader.nextString());
						} else if (nameRole.equals("salary")) {
							role.setSalary(reader.nextString());
						} else if (nameRole.equals("persons")) {
							reader.beginArray();
							while (reader.hasNext()) {
								reader.beginObject();

								Person person = new Person();
								person.setRole(role.getId());

								while (reader.hasNext()) {
									String namePerson = reader.nextName();
									if (namePerson.equals("id")) {
										person.setId(reader.nextString());
									} else if (namePerson.equals("name")) {
										person.setName(reader.nextString());
									}
								}
								persons.add(person);
								reader.endObject();
							}
							reader.endArray();
						}
					}
					roles.add(role);
					reader.endObject();
				}
				reader.endArray();
			}
		}
		reader.endObject();
		reader.close();
	} catch (IOException e) {

	}
}

Мы вызываем приведенный выше код в классе. XmlToJsonService.

JsonService jsonService = new JsonService();
List<Role> roles = new ArrayList<>();
List<Person> persons = new ArrayList<>();

jsonService.getDataFromJsonFile(filePathIn, roles, persons);

Конвертировать Java объекты в XML-сообщении с использованием JAXB

На этом этапе мы используем технику маршалинга JAXB.

Маршаллинг предоставляет клиентскому приложению возможность преобразовывать данные, полученные с помощью JAXB. Java дерево объектов в данные XML.

Определим функцию parseObjectToXml собрать Java Объект для XML-сообщения. Эта функция определена в классе. XMLService.

public void parseObjectToXml(String filePath, XMLModel xmlModel) {
	try {
		JAXBContext contextObj = JAXBContext.newInstance(XMLModel.class);

		Marshaller marshallerObj = contextObj.createMarshaller();
		marshallerObj.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

		marshallerObj.marshal(xmlModel, new FileOutputStream(filePath));
	} catch (JAXBException je) {
		System.out.println("JAXBException");
	} catch (IOException ie) {
		System.out.println("IOException");
	}
}

Мы вызываем приведенный выше код в классе. XmlToJsonService.

XMLService xmlService = new XMLService();
XMLModel xmlModel = new XMLModel();

Department department = new Department();
department.setRoles(roles);
department.setPersons(persons);

xmlModel.setDepartment(department);

xmlService.parseObjectToXml(filePathOut, xmlModel);

Это второй этап. Сгенерированный файл соответствует исходному файлу sample.xml, что подтверждает сохранение всех значений при передаче данных.

Как преобразовать JSON в XML в Java Без класса модели?

Описанный выше подход является правильным выбором, когда структура известна и стабильна, поскольку аннотированные классы документируют ее структуру.tracКогда структура неизвестна или часто меняется, универсальный конвертер работает быстрее.

org.json Библиотека выполняет преобразование в две строки, без использования каких-либо классов моделей:

import org.json.JSONObject;
import org.json.XML;

public class QuickConverter {

    public static void main(String[] args) {
        String str = "{\"username\":\"guru99user\",\"email\":\"guru99user@mail.com\"}";

        JSONObject json = new JSONObject(str);
        String xml = XML.toString(json);

        System.out.println(xml);
    }
}

Выход:

<username>guru99user</username><email>guru99user@mail.com</email>

Обратите внимание, что универсальный маршрут не создает ни корневого элемента, ни атрибутов, поэтому XML.toString(json, "root") Обычно это требуется. В таблице ниже два подхода представлены в сравнении друг с другом.

Критерий Gson с JAXB org.json generic conversion
Требуются модельные классы Да Нет
Контроль над структурой Полный, включая атрибуты Ограниченное количество, только элементы.
Решаping данным Возможно, как показано на примере вложенных лиц. Невозможно
Строки кода Много Две
лучше всего для Стабильные, документированные схемы произвольные или неизвестные структуры

JAXB считывает данные XML, а Gson записывает их в JSON, а обратный путь использует Gson для чтения. JSON данные, которые JAXB записывает обратно в XML. Для получения более подробной информации см. XML основы, более широкий Java учебник и ДжасперРепортс, который использует оба формата в качестве источников данных для отчетов.

Часто задаваемые вопросы (FAQ)

JAXB был удален из JDK в Java 11. Добавьте API jakarta.xml.bind вместе с средой выполнения, например jaxb-runtime, и обновите импорты с javax на jakarta.

Нет. Gson обрабатывает только JSON. XML сначала должен быть преобразован. Java объекты обрабатываются с помощью JAXB или другого парсера, например Jackson XML, прежде чем Gson сможет их сериализовать.

XmlElement создает дочерний тег, содержащий значение, а XmlAttribute помещает значение внутрь открывающего тега родительского тега. Атрибуты не могут содержать вложенные структуры.

Потоковая обработка данных позволяет снизить потребление памяти и дает возможность структуре выходных данных отличаться от входных классов, что в данном случае и происходит, когда люди вложены в роли.

Да, на примере XML-документа. Проверьте аннотации-обертки для коллекций, поскольку сгенерированные классы часто опускают XmlElementWrapper и создают плоскую структуру.

JSON и его вариант с разделителями строк доминируют, поскольку они напрямую соответствуют Python Словари и потоковая передача данных осуществляются эффективно. XML по-прежнему используется там, где устаревшие корпоративные системы предоставляют исходные данные.

Подведем итог этой публикации следующим образом: