Перетворення JSON на XML Java використання Gson та JAXB

⚡ Розумний підсумок

Перетворення JSON на XML Java використання Gson та JAXB за допомогою mapping обидва формати на один і той самий анотований Java класи. У цій статті визначено кожен формат, налаштовано проєкт, розпаковано XML за допомогою JAXB, записано JSON за допомогою Gson та виконано весь процес у зворотному порядку.

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

Конвертувати JSON в XML у Java

Що таке JSON?

JSON - це абревіатура від JavaНотація скриптових об'єктів – це формат даних, який відповідає правилам, які може прочитати більшість мов програмування. Ми можемо легко зберегти його у файлі або в базі даних. Формат JSON використовує пари ключ-значення для опису даних.

У наступному прикладі ми визначаємо рядок JSON, який зберігає особисту інформацію:

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

Отже, синтаксис JSON дуже простий. Кожен елемент даних має дві частини: ключ і значення, які відповідають назві поля та його значенню в записі. Якщо подивитися далі, то є кілька правил, подібних до цього:

  • Рядок JSON узятий у фігурні дужки {}.
  • Ключі JSON мають бути взяті в подвійні лапки, а рядкові значення також мають бути взяті в лапки.
  • Якщо даних більше (більше пар ключ => значення), ми використовуємо коми (,) для їх розділення.
  • Ключі JSON повинні використовувати звичайні літери, цифри або символ підкреслення без пробілів, а перший символ не повинен бути числом.

Що таке XML?

XML розшифровується як розширювана мова розмітки, запропонована Консорціумом Всесвітньої павутини (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, масив, об'єкт Тільки текст, типи походять зі схеми
Attributes Не підтримується Підтримується на будь-якому елементі
Коментарі Не підтримується Підтриманий
Багатослівність компактний Більш детальний, оскільки теги повторюються
Перевірка схеми Схема JSON, необов'язково DTD та XSD, зрілі
Типове використання Веб-API та конфігурація Корпоративні повідомлення та документи

Що таке Gson?

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

Починаючи з версії 1.6, Gson вводить два класи, JsonReader та ДжонсWriter, щоб забезпечити потокову обробку даних JSON.

  • ДжонсWriter – Потокове записування в JSON. Ми створюємо ДжонсWriter об'єкт. Щоб розпочати та завершити створення JSON-об'єкта, ми використовуємо функції beginObject() та endObject()Між цими двома викликами ми записуємо дані парами (ключ => значення).
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 Architecture for XML Binding, яка є бібліотекою, яка використовує анотації для перетворення Java об'єкти до XML-контенту і навпаки. Оскільки JAXB визначено специфікацією, ми можемо використовувати різні реалізації цього стандарту.

У JAXB ми часто використовуємо такі основні анотації:

  • @XmlRootElementЦя анотація вказує на найзовніший тег XML-файлу, і тому вона оголошується над класом.
  • @XmlElementWrapper: Ця анотація створює обгортку XML-елемент навколо колекцій.
  • @XmlElementЦя анотація оголошує, що властивість об'єкта стає дочірнім тегом XML-файлу.
  • @XmlAttribute: Ця анотація оголошує, що властивість об'єкта стає атрибутом навколишнього тегу.

Загальна реалізація така. Спочатку ми ініціалізуємо JAXBContext об'єкт за допомогою МійОб'єкт клас для конвертації.

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

Цей JAXBContext об'єкт має метод, який створює об'єкт, що перетворює XML-контент на Java об'єкт, той/та/те Unmarshaller.

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, Eclipse, та Gson працюють так само, з урахуванням вищезазначеної примітки JAXB.

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

Крок 1) Створити проект.
Створіть новий Java Проект.

Створіть новий Java Проект

Крок 2) Встановіть назву проекту.
Встановіть назву проекту на XmlToJsonExample.

Встановіть назву проекту

Крок 3) Створіть папку.
Створіть папку дані/введення що містить два файли sample.xml та sample.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;
	}
}

Person.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 Побудувати шлях

Якщо в проекті використовується Maven Замість ручного додавання 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.

Розпакування (Un-marshalling) надає клієнтській програмі можливість конвертувати 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

На цьому кроці ми визначаємо функцію writeDataToJsonFile записувати дані у JSON-файл. Ця функція визначена в класі JsonService.

Зверніть увагу, що для запису списку об'єктів JSON ми використовуємо функції beginArray() та endArray()Між цими двома викликами ми записуємо кожен 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 ми використовуємо функції beginArray() та endArray()Між цими двома викликами ми зчитуємо кожен 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.

Визначаємо функцію parsObjectToXml керувати 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
Необхідні класи моделей Так Немає
Контроль над структурою Повний, включаючи атрибути Обмежено, лише елементи
Решаping дані Можливо, як показано на прикладі вкладених осіб Неможливо
Рядки коду Багато Два
Найкраще для Стабільні, документовані схеми Спеціальні або невідомі структури

JAXB зчитує XML-дані, а Gson записує їх у JSON, а зворотний шлях використовує Gson для зчитування. JSON дані, поки JAXB записує їх назад у XML. Щоб дізнатися більше, перегляньте XML основи, ширше Java підручник та JasperReports, який використовує обидва формати як джерела даних звіту.

Поширені запитання

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 все ще з'являється там, де застарілі корпоративні системи надають вихідні дані.

Підсумуйте цей пост за допомогою: