Konverter JSON til XML Java ved hjælp af Gson og JAXB

⚡ Smart opsummering

Konverter JSON til XML Java brug af Gson og JAXB via kortping begge formater på den samme annoterede Java klasser. Denne artikel definerer hvert format, opsætter projektet, afkoder XML med JAXB, skriver JSON med Gson og vender hele processen om.

  • 🗝️ JSON-struktur: Data gemmes som nøgle- og værdipar i krøllede parenteser, med kommaer adskilt fra hinanden.
  • 🏷️ XML-struktur: Data gemmes i indlejrede noder, hvor hvert åbningstag kræver et matchende lukketag.
  • 🔗 Delt model: Et sæt kommenterede Java klasser fungerer som broen, så ingen af ​​formaterne parses direkte ind i det andet.
  • 📥 Afordentlig: JAXB læser en XML-fil og returnerer en udfyldt Java objekttræet gennem Unmarshaller-klassen.
  • 📤 Streamingskrivning: Gson JsonWriter udsender JSON trinvist med beginObject-, name-, value- og endObject-kald.
  • 🔄 Reverse Sti: JsonReader genopbygger objekterne fra JSON, og JAXB Marshaller skriver dem ud igen som XML.
  • ⚠️ Bemærkning om kørselstid: JAXB forlod JDK kl. Java 11, så jakarta.xml.bind-afhængigheden skal tilføjes eksplicit.

Konvertér JSON til XML i Java

Hvad er JSON?

JSON er en forkortelse for JavaScript Object Notation, som er et dataformat, der følger regler, som de fleste programmeringssprog kan læse. Vi kan nemt gemme det i en fil eller lagre det i en database. JSON-formatet bruger nøgle-værdi-par til at beskrive data.

I følgende eksempel definerer vi en JSON-streng, der gemmer personlige oplysninger:

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

Så syntaksen i JSON er meget enkel. Hvert dataelement har to dele, en nøgle og en værdi, som svarer til feltnavnet og dets værdi i en post. Ved nærmere eftersyn er der et par regler som denne:

  • JSON-strengen er omgivet af krøllede seler {}.
  • JSON-nøglerne skal være omgivet af dobbelte anførselstegn, og strengværdier skal også være i anførselstegn.
  • Hvis der er flere data (flere nøgle => værdipar), bruger vi kommaer (,) til at adskille dem.
  • JSON-nøgler skal bruge almindelige bogstaver, tal eller understregningstegnet uden mellemrum, og det første tegn må ikke være et tal.

Hvad er XML?

XML står for eXtensible Markup Language, foreslået af World Wide Web Consortium (https://www.w3.org/) til at oprette andre markup-sprog. Dette er en simpel delmængde, der kan beskrive mange forskellige typer data, så den er meget nyttig til deling af data mellem systemer.

Tags i XML er ofte ikke foruddefinerede, men de er oprettet efter brugerkonventioner. XML introducerer nye funktioner baseret på fordelene ved HTML.

Der er nogle nyttige XML-funktioner til forskellige systemer og løsninger:

  • XML kan udvides: XML giver dig mulighed for at oprette dine egne brugerdefinerede tags, der passer til din applikation.
  • XML bærer data, det viser dem ikke: XML giver dig mulighed for at gemme data uanset hvordan de vises.
  • XML er en fælles standard: XML er udviklet af World Wide Web Consortium (W3C) og er tilgængelig som en åben standard.

XML er bygget på en indlejret nodestruktur. Hver node har et åbningstag og et lukketag som følger:

<node>content</node>

Hvori:

  • er et åbent tag, og navnet på dette tag defineres af dig.
  • er et lukketag, og navnet på dette tag skal matche navnet på det åbne tag.
  • indhold er indholdet af dette tag.

Øverst i hver XML-fil skal du angive et tag for at angive den anvendte XML-version. Syntaksen for instruktionstagget:

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

JSON vs XML: Vigtigste forskelle

Begge formater indeholder strukturerede data, og tabellen nedenfor viser, hvorfor et projekt muligvis skal skifte mellem dem.

Parameter JSON XML
Syntaksstil Nøgle- og værdipar Indlejrede tags
Datatyper Streng, tal, boolsk, nul, array, objekt Kun tekst, typer kommer fra et skema
Attributter Ikke understøttet Understøttes på ethvert element
Kommentarer Ikke understøttet Understøttet
informationsmængde Kompakt Mere ordrig fordi tags gentages
Skema validering JSON-skema, valgfrit DTD og XSD, moden
Typisk brug Web-API'er og konfiguration Virksomhedsmeddelelser og dokumenter

Hvad er Gson?

Gson (https://github.com/google/gson) er en Java bibliotek, der giver brugerne mulighed for at konvertere en Java objekt til en JSON-streng, og også til at konvertere en JSON-streng tilbage til en Java objekt. Gson kan arbejde med vilkårlig Java objekter, inklusive eksisterende objekter, hvis kildekode du ikke har.

Siden version 1.6 introducerer Gson to klasser, JsonReader og jSONWriter, for at muliggøre streamingbehandling af JSON-data.

  • jSONWriter – Streaming af skrivning til JSON. Vi opretter en jSONWriter objekt. For at starte og afslutte oprettelsen af ​​et JSON-objekt bruger vi funktionerne startObject() og endObject()Mellem disse to kald skriver vi data som par (nøgle => værdi).
JsonWriter writer = new JsonWriter();
writer.beginObject();
writer.name("key").value("value");
writer.endObject();
  • JsonReader – Streaming af læsning fra JSON. Vi opretter et JsonReader-objekt. For at starte og afslutte læsningen af ​​et JSON-objekt bruger vi funktionerne beginObject() og endObject(). Mellem disse to kald læser vi data som par (nøgle => værdi).
JsonReader reader = new JsonReader();
reader.beginObject();
while (reader.hasNext()) {
	String name = reader.nextName();
	if (name.equals("key")) {
		String value = reader.nextString();
	}
}
reader.endObject();

Gson-streamingbehandling er hurtig. Du skal dog selv håndtere hvert par (nøgle => værdi) af JSON-dataene.

Hvad er JAXB?

JAXB står for Java Architecture for XML Binding, som er et bibliotek, der bruger annoteringer til at konvertere Java objekter til XML-indhold og omvendt. Da JAXB er defineret af en specifikation, kan vi bruge forskellige implementeringer af denne standard.

Med JAXB bruger vi ofte følgende grundlæggende annotationer:

  • @XmlRootElementDenne annotation angiver det yderste tag i XML-filen, og det er derfor deklareret over en klasse.
  • @XmlElementWrapper: Denne annotation opretter et XML-indpakningselement omkring samlinger.
  • @XmlElementDenne annotation erklærer, at en egenskab ved objektet bliver et underordnet tag til XML-filen.
  • @XmlAttributeDenne annotation erklærer, at en egenskab ved objektet bliver en attribut på det omgivende tag.

Den generelle implementering er som følger. Først initialiserer vi JAXBContekst objekt med Mit objekt klasse at konvertere.

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

Denne JAXBContekst objektet har en metode, der opretter et objekt, som konverterer XML-indhold til en Java objektet, den Unmarshaller.

Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();

Det samme JAXBContekst objektet har også en metode, der opretter objektet, som konverterer en Java objekt ind i XML-indhold, Marshaller.

Marshaller marshallerObj = jaxbContext.createMarshaller();

⚠️ Advarsel: JAXB blev fjernet fra JDK i Java 11. På Java 11 og nyere, tilføj API'en og en runtime-implementering eksplicit til projektet, for eksempel jakarta.xml.bind:jakarta.xml.bind-api Sammen med org.glassfish.jaxb:jaxb-runtimeog importer annotationerne fra jakarta.xml.bind.annotation i stedet for javax.xml.bind.annotation.

Sådan konverteres XML til JSON?

Vi implementerer eksemplet med konvertering fra XML til JSON på følgende platform. Versionerne nedenfor er dem, der bruges til skærmbillederne. Nyere versioner af JDK, Eclipse, og Gson fungerer på samme måde, med forbehold for JAXB-noten ovenfor.

  • OpenJDK 8 til Ubuntu 18.04 x64.
  • Eclipse IDE 2019-03 (4.11.0) x64 Java Udvikling for Ubuntu.
  • Gson 2.8.5.

Trin 1) Opret projekt.
Opret en ny Java projekt.

Opret en ny Java Projekt.

Trin 2) Angiv projektnavn.
Sæt projektnavnet til XmlToJsonEksempel.

Indstil projektnavn

Trin 3) Opret en mappe.
Opret mappen data/input indeholder de to filer sample.xml og sample.json.

Opret mappedata

Lad os først definere vores XML med afdeling, rolleog person, egenskaber.

Den generelle arkitektur er: én afdeling har mange roller, og én rolle har mange personer. Diagrammet nedenfor viser disse relationer.

Objektforhold

<?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>

For det andet definerer vi den JSON, der udtrykker den samme idé. Bemærk, at den flade personliste bliver et indlejret array i hver rolle, hvilket er præcis den transformation, som konverteringskoden udfører.

{
	"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"
				}
			]
		}
	]
}

Trin 4) Definer objekter.
Definer de tilsvarende objektklasser i pakken model.

Definer objektklasser

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

Afdeling.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;
	}

}

Trin 5) Opsæt biblioteket.
Tilføj og opsæt Gson 2.8.5-biblioteket i Java Byg sti.

Konfigurer biblioteket Gson

Tilføj bibliotek Gson 2.8.5 til Java Byg sti

Hvis projektet bruger Maven I stedet for en manuelt tilføjet jar, erklæres de samme biblioteker som afhængigheder. Version 2.8.5 er fastgjort her for at matche skærmbillederne, og enhver senere Gson-udgivelse fungerer identisk for dette eksempel:

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

Konverter XML-meddelelse til Java objekter ved hjælp af JAXB

Først definerer vi de udøvende klasser i pakken service.

Definer udførende klasser

I det første trin i den første proces bruger vi JAXB's un-marshalling-teknik.

Un-marshalling giver en klientapplikation mulighed for at konvertere XML-data til JAXB-afledte data. Java objekter.

Vi definerer funktionen getObjectFromXmlFile at fjerne samlingen af ​​vores XML-fil tilbage til en Java objekt. Denne funktion er defineret i klassen 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;
	}
}

Vi kalder ovenstående kode i klassen XmlToJsonService.

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

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

På dette tidspunkt er XML-filen blevet til tre Java objekter i hukommelsen. Det næste trin skriver dem ud som JSON.

Konverter Java protesterer mod JSON-meddelelse ved hjælp af Gson

I dette trin definerer vi funktionen writeDataToJsonFile at skrive data til JSON-filen. Denne funktion er defineret i klassen JsonService.

Bemærk at for at skrive en liste over JSON-objekter bruger vi funktionerne beginArray() og endArray()Mellem disse to kald skriver vi hvert JSON-objekt.

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) {
	}
}

Vi kalder ovenstående kode i klassen XmlToJsonService.

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

Det er den første proces. Den indre løkke matcher hver person med det aktuelle rolle-id, hvilket er sådan den flade XML-personliste bliver til et indlejret JSON-array.

Konverter JSON-meddelelse til Java objekter ved hjælp af Gson

I det første trin i den anden proces definerer vi funktionen getDataFromJsonFile at læse data fra JSON-filen. Denne funktion er defineret i klassen JsonService.

Bemærk at for at læse en liste over JSON-objekter bruger vi funktionerne beginArray() og endArray()Mellem disse to kald læser vi hvert JSON-objekt.

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

	}
}

Vi kalder ovenstående kode i klassen XmlToJsonService.

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

jsonService.getDataFromJsonFile(filePathIn, roles, persons);

Konverter Java objekter til XML-meddelelse ved hjælp af JAXB

I dette trin bruger vi JAXBs marshallingteknik.

Marshalling giver en klientapplikation mulighed for at konvertere en JAXB-afledt Java objekttræ til XML-data.

Vi definerer funktionen parseObjectToXml at marskalere Java objekt til en XML-meddelelse. Denne funktion er defineret i klassen 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");
	}
}

Vi kalder ovenstående kode i klassen 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);

Det er den anden proces. Den genererede fil matcher den originale sample.xml, hvilket bekræfter, at returprocessen bevarede alle værdier.

Sådan konverterer du JSON til XML i Java uden en modelklasse?

Ovenstående fremgangsmåde er det rigtige valg, når strukturen er kendt og stabil, fordi de annoterede klasser dokumenterer konsekvensen.tract. Når strukturen er ukendt eller ændrer sig ofte, er en generisk konverter hurtigere.

org.json biblioteket udfører konverteringen i to linjer uden nogen modelklasse:

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

Output:

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

Bemærk at den generiske rute ikke producerer noget rodelement og ingen attributter, så XML.toString(json, "root") er normalt påkrævet. Tabellen nedenfor viser de to tilgange side om side.

Kriterium Gson med JAXB org.json generisk konvertering
Modelklasser kræves Ja Ingen
Kontrol over struktur Fuld, inklusive attributter Begrænset, kun elementer
Reshaping data Muligt, som vist med indbyggede personer Ikke muligt
Linjer med kode Mange to
Bedste for Stabile, dokumenterede skemaer Ad hoc- eller ukendte strukturer

JAXB læser XML-data, og Gson skriver dem til JSON, og den omvendte sti bruger Gson til at læse JSON data, mens JAXB skriver dem tilbage til XML. For at gå videre, gennemgå XML grundlæggende elementer, den bredere Java tutorialog Jasper Rapporter, som bruger begge formater som rapportdatakilder.

Ofte Stillede Spørgsmål

JAXB blev fjernet fra JDK i Java 11. Tilføj jakarta.xml.bind API'en sammen med en runtime som f.eks. jaxb-runtime, og opdater importerne fra javax til jakarta.

Nej. Gson håndterer kun JSON. XML skal først blive Java objekter via JAXB, eller gennem en anden parser såsom Jackson XML, før Gson kan serialisere det.

XmlElement producerer et underordnet tag, der indeholder værdien, mens XmlAttribute placerer værdien inde i det indledende tag fra det overordnede element. Attributter kan ikke indeholde indbyggede strukturer.

Streaming holder hukommelsesforbruget lavt og tillader outputstrukturen at afvige fra inputklasserne, hvilket er præcis, hvad der sker, når personer er indlejret i roller her.

Ja, fra et eksempel på et XML-dokument. Bekræft wrapper-annotationerne på samlinger, fordi genererede klasser ofte udelader XmlElementWrapper og producerer en flad struktur.

JSON og dens linjeafgrænsede variant dominerer, fordi de knyttes direkte til Python ordbøger og stream effektivt. XML vises stadig, hvor ældre virksomhedssystemer leverer kildedataene.

Opsummer dette indlæg med: