Конвертирайте JSON в XML Java използвайки Gson и JAXB

⚡ Умно обобщение

Конвертирайте JSON в XML Java използване на Gson и JAXB от картатаping и двата формата върху един и същ анотиран Java класове. Тази статия дефинира всеки формат, настройва проекта, демаршалира XML с JAXB, записва JSON с Gson и обръща целия процес.

  • 🗝️ JSON структура: Данните се съхраняват като двойки ключ и стойност, оградени в къдрави скоби, като всеки запис е разделен от запетаи.
  • ???? ️ XML структура: Данните се съхраняват във вложени възли, където всеки отварящ таг изисква съответстващ затварящ таг.
  • 🔗 Споделен модел: Един набор от анотирани Java класовете действат като мост, така че нито един от форматите не се анализира директно в другия.
  • 📥 Разгръщане: JAXB чете XML файл и връща попълнен Java дърво на обектите чрез класа Unmarshaller.
  • 📤 Стрийминг запис: Gson JsonWriter Излъчва JSON инкрементално с извиквания на beginObject, name, value и endObject.
  • 🔄 Reverse Path: 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 е съкращение от eXtensible Markup Language (разширяем език за маркиране), предложен от World Wide Web Consortium (https://www.w3.org/) за създаване на други езици за маркиране. Това е просто подмножество, което може да описва много различни типове данни, така че е много полезно за споделяне на данни между системи.

Етикетите в XML често не са предварително дефинирани, но се създават според потребителските конвенции. XML въвежда нови функции, базирани на предимствата на HTML.

Има някои полезни XML функции за различни системи и решения:

  • XML е разширяем: XML ви позволява да създавате свои собствени персонализирани тагове, които да отговарят на вашето приложение.
  • XML пренася данни, а не ги показва: XML ви позволява да съхранявате данни, независимо от това как ще бъдат показани.
  • XML е общ стандарт: XML е разработен от World Wide Web Consortium (W3C) и се предлага като отворен стандарт.

XML е изграден върху вложена структура на възли. Всеки възел има отварящ таг и затварящ таг, както следва:

<node>content</node>

В който:

  • е отворен етикет и името на този етикет се определя от вас.
  • е затварящ таг и името на този таг трябва да съвпада с името на отварящия таг.
  • съдържание е съдържанието на този етикет.

В началото на всеки XML файл трябва да декларирате таг, който указва използваната XML версия. Синтаксисът на тага за инструкция:

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

JSON срещу XML: Ключови разлики

И двата формата съдържат структурирани данни, а таблицата по-долу показва защо може да се наложи проектът да превключва между тях.

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

Какво е Gson?

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

От версия 1.6 насам, Gson въвежда два класа, JsonReader намлява JsonWriter, за да се осигури стрийминг обработка на JSON данни.

  • JsonWriter – Стрийминг на запис в JSON. Създаваме JsonWriter обект. За да започнем и завършим създаването на 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 за XML Binding, която е библиотека, която използва анотации за конвертиране Java обекти към XML съдържание и обратно. Тъй като JAXB е дефиниран от спецификация, можем да използваме различни имплементации на този стандарт.

С JAXB често използваме следните основни анотации:

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

Общата имплементация е следната. Първо, инициализираме JAXBCонтекст обект с MyObject клас за конвертиране.

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

Това JAXBCонтекст обектът има метод, който създава обект, преобразуващ XML съдържание в Java обектът, на Unmarshaller.

Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();

Същият JAXBCонтекст обектът също има метод, който създава обекта, който преобразува a 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.

Размаршалингът предоставя на клиентското приложение възможността да конвертира 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.

Marshalling предоставя на клиентското приложение възможността да конвертира 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 без Моделен клас?

Горният подход е правилният избор, когато структурата е позната и стабилна, защото анотираните класове документират contracт. Когато структурата е неизвестна или се променя често, генеричният конвертор е по-бърз.

- 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 данни Възможно е, както е показано с вложени лица Не е възможно
Редове код Много две
Най - доброто за Стабилни, документирани схеми Ad hoc или неизвестни структури

JAXB чете XML данни, а Gson ги записва в JSON, а обратният път използва Gson за четене. JSON данни, докато JAXB ги записва обратно в XML. За да продължите по-нататък, прегледайте XML основи, по-широкият Java настойнически, и JasperReports, който използва и двата формата като източници на данни за отчети.

Въпроси и Отговори

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

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

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

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

Да, от примерен XML документ. Проверете анотациите на обвивката на колекциите, защото генерираните класове често пропускат XmlElementWrapper и създават сплескана структура.

JSON и неговият вариант с разделители на линии доминират, защото се картографират директно върху Python речници и ефективно стриймване. XML все още се появява там, където остарелите корпоративни системи предоставят изходните данни.

Обобщете тази публикация с: