Java XML und JSON: Dokumentverarbeitung für Java SE, Teil 2: JSON-B

In diesem Artikel werden wir XML und JSON in Java 11 und darüber hinaus weiter untersuchen.

Beispiele in diesem Artikel führen Sie in JSON-B ein, die JSON-Bindungs-API für Java. Nach einem kurzen Überblick und einer Installationsanleitung werde ich Ihnen zeigen, wie Sie mit JSON-B Java-Objekte, Arrays und Sammlungen serialisieren und deserialisieren. Anpassen der Serialisierung und Deserialisierung mit JSON-B; und wie man JSON-B-Adapter verwendet, um Quellobjekte während der Serialisierung oder Deserialisierung in Zielobjekte zu konvertieren.

Das Material für diesen Artikel ist völlig neu, könnte aber als zusätzliches Kapitel (Kapitel 13) für mein neues Buch angesehen werden, das kürzlich von Apress veröffentlicht wurde: Java XML und JSON, Second Edition .

Über das Buch: Java XML und JSON

Wie ich bereits in meinem vorherigen Artikel erwähnt habe, hat Apress gerade die zweite Ausgabe meines Buches Java XML und JSON veröffentlicht . Es war mir eine Freude, ein ganzes Buch über XML und JSON zu schreiben, zwei Technologien, die ich für komplementärer als wettbewerbsfähig halte. Nach der Veröffentlichung des Buches habe ich neue Beispiele für Kapitel 6: Transformieren von XML-Dokumenten mit XSLT und für Kapitel 11: Verarbeiten von JSON mit Jackson hinzugefügt. In meinem letzten Artikel "Java XML und JSON: Dokumentverarbeitung für Java SE, Teil 1" wurden verschiedene Techniken zur Transformation und Verarbeitung von Dokumenten unter Verwendung von SAXON und Jackson vorgestellt. Lesen Sie unbedingt diesen Artikel, um mehr über diese Techniken zu erfahren.

Holen Sie sich den Code

Laden Sie den Quellcode herunter, um Beispiele für dieses Tutorial zu erhalten.

Was ist JSON-B?

JSON-B ist eine Standardbindungsschicht und API zum Konvertieren von Java-Objekten in und aus JSON-Dokumenten. Es ähnelt der Java-Architektur für XML-Bindung (JAXB), mit der Java-Objekte in und aus XML konvertiert werden.

JSON-B basiert auf JSON-P, der JSON-Verarbeitungs-API, die zum Parsen, Generieren, Abfragen und Transformieren von JSON-Dokumenten verwendet wird. JSON-B wurde mehr als ein Jahr nach der endgültigen Veröffentlichung von JSR 353, dem JSR für JSON-P, durch Java Specification Request (JSR) 367 eingeführt.

Die JSON-B-API

Die JSON-B-Website (Java API for JSON Binding) führt JSON-B ein und bietet Zugriff auf verschiedene Ressourcen, einschließlich der API-Dokumentation. Gemäß der Dokumentation speichert das JSON-B-Modul sechs Pakete:

  • javax.json.bind: Definiert den Einstiegspunkt zum Binden von Java-Objekten an JSON-Dokumente.
  • javax.json.bind.adapter: Definiert adapterbezogene Klassen.
  • javax.json.bind.annotation: Definiert Anmerkungen zum Anpassen der Zuordnung zwischen Java-Programmelementen und JSON-Dokumenten.
  • javax.json.bind.config: Definiert Strategien und Richtlinien zum Anpassen der Zuordnung zwischen Java-Programmelementen und JSON-Dokumenten.
  • javax.json.bind.serializer: Definiert Schnittstellen zum Erstellen benutzerdefinierter Serializer und Deserializer.
  • javax.json.bind.spi: Definiert eine Service Provider-Schnittstelle (SPI) zum Einstecken von benutzerdefinierten JsonbBuilders.

Die JSON-B-Website enthält außerdem einen Link zu Yasson, einem Java-Framework, das eine Standardbindungsebene zwischen Java-Klassen und JSON-Dokumenten bereitstellt, sowie eine offizielle Referenzimplementierung der JSON-Bindungs-API.

JSON-B und Java EE 8

Wie JSON-P wurde JSON-B ursprünglich für die Aufnahme in Java SE in Betracht gezogen, wurde jedoch stattdessen in die Java EE 8-Version aufgenommen. Sie können jedoch weiterhin mit JSON-B in einem Java SE-Kontext arbeiten.

Laden Sie JSON-B herunter und installieren Sie es

JSON-B 1.0 ist die aktuelle Version zum Zeitpunkt des Schreibens. Sie können die Yasson-Referenzimplementierung dieser Bibliothek aus dem Maven-Repository beziehen. Sie müssen die folgenden JAR-Dateien herunterladen:

  • Javax JSON Bind API 1.0: Enthält alle JSON-B-Klassendateien. Ich habe heruntergeladen javax.json.bind-api-1.0.jar.
  • Yasson: Enthält die Eclipse-basierte Referenzimplementierung von JSON-B. Ich habe heruntergeladen yasson-1.0.3.jar.
  • JSR 374 (JSON-Verarbeitung) Standardanbieter: Enthält alle JSON-P 1.0-Klassendateien zusammen mit den Glassfish-Standardanbieter-Klassendateien. Ich habe heruntergeladen javax.json-1.1.4.jar.

Fügen Sie diese JAR-Dateien zu Ihrem Klassenpfad hinzu, wenn Sie Code kompilieren und ausführen, der diese Bibliotheken verwendet:

javac -cp javax.json.bind-api-1.0.jar;. main source file java -cp javax.json.bind-api-1.0.jar;yasson-1.0.3.jar;javax.json-1.1.4.jar;. main classfile

Serialisieren und Deserialisieren von Java-Objekten mit JSON-B

Das javax.json.bindPaket enthält die Jsonbund JsonbBuilder-Schnittstellen, die als Einstiegspunkt für diese Bibliothek dienen:

  • Jsonbbietet überladene toJson()Methoden zum Serialisieren von Bäumen von Java-Objekten in JSON-Dokumente und fromJson()Methoden zum Deserialisieren von JSON-Dokumenten in Bäume von Java-Objekten.
  • JsonbBuilderbietet newBuilder()und andere Methoden zum Abrufen eines neuen Builders build()sowie create()Methoden zum Zurückgeben neuer JsonbObjekte.

Das folgende Codebeispiel zeigt die grundlegende Verwendung der Typen Jsonbund JsonBuilder:

// Create a new Jsonb instance using the default JsonbBuilder implementation. Jsonb jsonb = JsonbBuilder.create(); // Create an Employee object from a hypothetical Employee class. Employee employee = ... // Convert the Employee object to a JSON document stored in a string. String jsonEmployee = jsonb.toJson(employee); // Convert the previously-created JSON document to an Employee object. Employee employee2 = jsonb.fromJson(jsonEmployee, Employee.class);

Dieses Beispiel aufruft Jsonb‚s String toJson(Object object)Methode ein Java - Objekt zu serialisiert, ( Employee). Dieser Methode wird das Stammverzeichnis des Java-Objektbaums zur Serialisierung übergeben. Wenn nullbestanden wird, toJson()wirft java.lang.NullPointerException. Es wird ausgelöst, javax.json.bind.JsonbExceptionwenn während der Serialisierung ein unerwartetes Problem (z. B. ein E / A-Fehler) auftritt.

Dieses Codefragment ruft auch Jsonb‚s T fromJson(String str, Class type)generische Methode, die für die Deserialisierung verwendet wird. Dieser Methode wird das auf Zeichenfolgen basierende JSON-Dokument zum Deserialisieren und der Typ des Stammobjekts des resultierenden Java-Objektbaums übergeben, das zurückgegeben wird. Diese Methode löst aus, NullPointerExceptionwenn sie nullan einen der Parameter übergeben wird. Es wird ausgelöst, JsonbExceptionwenn während der Deserialisierung ein unerwartetes Problem auftritt.

Ich habe das Codefragment aus einer JSONBDemoAnwendung extrahiert, die eine grundlegende Demonstration von JSON-B bietet. Listing 1 zeigt den Quellcode für diese Demo.

Listing 1. JSONBDemo.java (Version 1)

import java.time.LocalDate; import javax.json.bind.Jsonb; import javax.json.bind.JsonbBuilder; public class JSONBDemo { public static void main(String[] args) { Jsonb jsonb = JsonbBuilder.create(); Employee employee = new Employee("John", "Doe", 123456789, false, LocalDate.of(1980, 12, 23), LocalDate.of(2002, 8, 14)); String jsonEmployee = jsonb.toJson(employee); System.out.println(jsonEmployee); System.out.println(); Employee employee2 = jsonb.fromJson(jsonEmployee, Employee.class); System.out.println(employee2); } }

main()Erstellt zuerst ein JsonbObjekt, gefolgt von einem EmployeeObjekt. Anschließend wird toJson()aufgerufen, das EmployeeObjekt in ein JSON-Dokument zu serialisieren , das in einer Zeichenfolge gespeichert ist. main()Ruft nach dem Drucken dieses Dokuments fromJson()mit der vorherigen Zeichenfolge und Employeedem java.lang.ClassObjekt auf, um das JSON-Dokument für ein anderes EmployeeObjekt zu deserialisieren , das anschließend gedruckt wird.

Listing 2 zeigt Employeeden Quellcode.

Listing 2. Employee.java (Version 1)

import java.time.LocalDate; public class Employee { private String firstName; private String lastName; private int ssn; private boolean isMarried; private LocalDate birthDate; private LocalDate hireDate; private StringBuffer sb = new StringBuffer(); public Employee() {} public Employee(String firstName, String lastName, int ssn, boolean isMarried, LocalDate birthDate, LocalDate hireDate) { this.firstName = firstName; this.lastName = lastName; this.ssn = ssn; this.isMarried = isMarried; this.birthDate = birthDate; this.hireDate = hireDate; } public String getFirstName() { return firstName; } public String getLastName() { return lastName; } public int getSSN() { return ssn; } public boolean isMarried() { return isMarried; } public LocalDate getBirthDate() { return birthDate; } public LocalDate getHireDate() { return hireDate; } public void setFirstName(String firstName) { this.firstName = firstName; } public void setLastName(String lastName) { this.lastName = lastName; } public void setSSN(int ssn) { this.ssn = ssn; } public void setIsMarried(boolean isMarried) { this.isMarried = isMarried; } public void setBirthDate(LocalDate birthDate) { this.birthDate = birthDate; } public void setHireDate(LocalDate hireDate) { this.hireDate = hireDate; } @Override public String toString() { sb.setLength(0); sb.append("First name ["); sb.append(firstName); sb.append("], Last name ["); sb.append(lastName); sb.append("], SSN ["); sb.append(ssn); sb.append("], Married ["); sb.append(isMarried); sb.append("], Birthdate ["); sb.append(birthDate); sb.append("], Hiredate ["); sb.append(hireDate); sb.append("]"); return sb.toString(); } }

Stellen Sie die Listen 1 und 2 wie folgt zusammen:

javac -cp javax.json.bind-api-1.0.jar;. JSONBDemo.java

Führen Sie die Anwendung wie folgt aus:

java -cp javax.json.bind-api-1.0.jar;yasson-1.0.3.jar;javax.json-1.1.4.jar;. JSONBDemo

You should observe the following output (spread across multiple lines for readability):

{"SSN":123456789,"birthDate":"1980-12-23","firstName":"John","hireDate":"2002-08-14", "lastName":"Doe","married":false} First name [John], Last name [Doe], SSN [123456789], Married [false], Birthdate [1980-12-23], Hiredate [2002-08-14] 

Rules for working with JSON-B

While playing with this application, I observed some interesting behaviors that led me to formulate the following rules concerning Employee:

  • The class must be public; otherwise, an exception is thrown.
  • toJson() will not serialize fields with non-public getter methods.
  • fromJson() will not deserialize fields with non-public setter methods.
  • fromJson() throws JsonbException in the absence of a public noargument constructor.

In order to seamlessly convert between Java object fields and JSON data, JSON-B has to support various Java types. For example, JSON-B supports the following basic Java types:

  • java.lang.Boolean
  • java.lang.Byte
  • java.lang.Character
  • java.lang.Double
  • java.lang.Float
  • java.lang.Integer
  • java.lang.Long
  • java.lang.Short
  • java.lang.String

Weitere Typen wie java.math.BigInteger, java.util.Dateund java.time.LocalDatewerden unterstützt. In der JSON-B-Spezifikation finden Sie eine vollständige Liste der unterstützten Typen.

Serialisieren und Deserialisieren von Arrays und Sammlungen mit JSON-B

Der vorherige Abschnitt befasste sich mit der Serialisierung und Deserialisierung einzelner Java-Objekte. JSON-B unterstützt auch die Möglichkeit, Objektarrays und -sammlungen zu serialisieren und zu deserialisieren. Listing 3 bietet eine Demonstration.

Listing 3. JSONBDemo.java (Version 2)

import java.time.LocalDate; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import javax.json.bind.Jsonb; import javax.json.bind.JsonbBuilder; public class JSONBDemo { public static void main(String[] args) { arrayDemo(); listDemo(); } // Serialize and deserialize an array of Employee objects. static void arrayDemo() { Jsonb jsonb = JsonbBuilder.create(); Employee[] employees = { new Employee("John", "Doe", 123456789, false, LocalDate.of(1980, 12, 23), LocalDate.of(2002, 8, 14)), new Employee("Jane", "Smith", 987654321, true, LocalDate.of(1982, 6, 13), LocalDate.of(2001, 2, 9)) }; String jsonEmployees = jsonb.toJson(employees); System.out.println(jsonEmployees); System.out.println(); employees = null; employees = jsonb.fromJson(jsonEmployees, Employee[].class); for (Employee employee: employees) { System.out.println(employee); System.out.println(); } } // Serialize and deserialize a List of Employee objects. static void listDemo() { Jsonb jsonb = JsonbBuilder.create(); List employees = Arrays.asList(new Employee("John", "Doe", 123456789, false, LocalDate.of(1980, 12, 23), LocalDate.of(2002, 8, 14)), new Employee("Jane", "Smith", 987654321, true, LocalDate.of(1982, 6, 13), LocalDate.of(1999, 7, 20))); String jsonEmployees = jsonb.toJson(employees); System.out.println(jsonEmployees); System.out.println(); employees = null; employees = jsonb.fromJson(jsonEmployees, new ArrayList(){}. getClass().getGenericSuperclass()); System.out.println(employees); } }

Listing 3 ist eine einfache Erweiterung von Listing 1 und verwendet dieselbe EmployeeKlasse wie Listing 2. Darüber hinaus ruft dieses Codebeispiel dasselbe toJson()und dieselben fromJson()Methoden auf.