Java XML e JSON: elaborazione dei documenti per Java SE, parte 2: JSON-B

In questo articolo, continueremo a esplorare XML e JSON in Java 11 e oltre.

Gli esempi in questo articolo ti introdurranno a JSON-B, l'API di associazione JSON per Java. Dopo una rapida panoramica e istruzioni di installazione, ti mostrerò come utilizzare JSON-B per serializzare e deserializzare oggetti, array e raccolte Java; come personalizzare la serializzazione e la deserializzazione utilizzando JSON-B; e come utilizzare gli adattatori JSON-B per convertire gli oggetti di origine in oggetti di destinazione durante la serializzazione o la deserializzazione.

Il materiale per questo articolo è completamente nuovo, ma potrebbe essere considerato un capitolo aggiuntivo (Capitolo 13) per il mio nuovo libro, recentemente pubblicato da Apress: Java XML e JSON, Seconda Edizione .

Informazioni sul libro: Java XML e JSON

Come ho condiviso nel mio precedente articolo, Apress ha appena pubblicato la seconda edizione del mio libro, Java XML e JSON . È stato un piacere scrivere un intero libro su XML e JSON, due tecnologie che considero più complementari che competitive. Dopo la pubblicazione del libro, ho aggiunto nuovi esempi per il Capitolo 6: Trasformazione di documenti XML con XSLT e per il Capitolo 11: Elaborazione di JSON con Jackson. Il mio ultimo articolo, "Java XML e JSON: elaborazione di documenti per Java SE, parte 1", ha introdotto una varietà di tecniche di trasformazione ed elaborazione dei documenti utilizzando SAXON e Jackson. Assicurati di controllare l'articolo per saperne di più su queste tecniche.

Ottieni il codice

Scarica il codice sorgente per gli esempi utilizzati in questo tutorial.

Cos'è JSON-B?

JSON-B è un livello di associazione standard e un'API per la conversione di oggetti Java in e da documenti JSON. È simile a Java Architecture for XML Binding (JAXB), utilizzato per convertire oggetti Java in e da XML.

JSON-B è basato su JSON-P, l'API di elaborazione JSON utilizzata per analizzare, generare, eseguire query e trasformare documenti JSON. JSON-B è stato introdotto da Java Specification Request (JSR) 367 più di un anno dopo il rilascio finale di JSR 353, il JSR per JSON-P.

L'API JSON-B

Il sito Web Java API for JSON Binding (JSON-B) introduce JSON-B e fornisce l'accesso a varie risorse, inclusa la documentazione API. Secondo la documentazione, il modulo JSON-B memorizza sei pacchetti:

  • javax.json.bind: Definisce il punto di ingresso per l'associazione di oggetti Java a documenti JSON.
  • javax.json.bind.adapter: Definisce le classi relative all'adattatore.
  • javax.json.bind.annotation: Definisce le annotazioni per personalizzare la mappatura tra gli elementi del programma Java e i documenti JSON.
  • javax.json.bind.config: Definisce strategie e politiche per personalizzare la mappatura tra gli elementi del programma Java e i documenti JSON.
  • javax.json.bind.serializer: Definisce le interfacce per la creazione di serializzatori e deserializzatori personalizzati.
  • javax.json.bind.spi: Definisce un'interfaccia SPI (Service Provider Interface) per il collegamento di messaggi personalizzati JsonbBuilder.

Il sito Web JSON-B fornisce anche un collegamento a Yasson, un framework Java che fornisce un livello di associazione standard tra classi Java e documenti JSON e un'implementazione di riferimento ufficiale dell'API di associazione JSON.

JSON-B e Java EE 8

Come JSON-P, JSON-B è stato originariamente considerato per l'inclusione in Java SE, ma è stato invece incluso nella versione Java EE 8. Tuttavia, puoi ancora lavorare con JSON-B in un contesto Java SE.

Scarica e installa JSON-B

JSON-B 1.0 è la versione corrente al momento della scrittura. È possibile ottenere l'implementazione di riferimento Yasson di questa libreria dal repository Maven. Dovrai scaricare i seguenti file JAR:

  • Javax JSON Bind API 1.0: contiene tutti i file di classe JSON-B. Ho scaricato javax.json.bind-api-1.0.jar.
  • Yasson: contiene l'implementazione di riferimento basata su Eclipse di JSON-B. Ho scaricato yasson-1.0.3.jar.
  • Provider predefinito JSR 374 (elaborazione JSON): contiene tutti i file di classe JSON-P 1.0 insieme ai file di classe del provider predefinito Glassfish. Ho scaricato javax.json-1.1.4.jar.

Aggiungi questi file JAR al tuo classpath durante la compilazione e l'esecuzione di codice che utilizza queste librerie:

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

Serializzazione e deserializzazione di oggetti Java con JSON-B

Il javax.json.bindpacchetto fornisce le interfacce Jsonbe JsonbBuilder, che fungono da punto di accesso a questa libreria:

  • Jsonbfornisce toJson()metodi sovraccaricati per serializzare alberi di oggetti Java in documenti JSON e fromJson()metodi per deserializzare documenti JSON in alberi di oggetti Java.
  • JsonbBuilderfornisce newBuilder()e altri metodi per ottenere un nuovo generatore build()e create()metodi per restituire nuovi Jsonboggetti.

Nell'esempio di codice seguente viene illustrato l'utilizzo di base dei tipi Jsonbe 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);

Questo esempio richiama Jsonbil String toJson(Object object)metodo di per serializzare un oggetto Java, ( Employee). Questo metodo viene passato alla radice dell'albero degli oggetti Java da serializzare. Se nullviene passato, toJson()lancia java.lang.NullPointerException. Viene generato javax.json.bind.JsonbExceptionquando si verifica un problema imprevisto (come un errore di I / O) durante la serializzazione.

Questo frammento di codice richiama anche Jsonbil T fromJson(String str, Class type)metodo generico di, utilizzato per la deserializzazione. A questo metodo viene passato il documento JSON basato su stringa da deserializzare e il tipo di oggetto radice dell'albero di oggetti Java risultante, che viene restituito. Questo metodo genera NullPointerExceptionquando nullviene passato a uno dei parametri; viene generato JsonbExceptionquando si verifica un problema imprevisto durante la deserializzazione.

Ho estratto il frammento di codice da JSONBDemoun'applicazione che fornisce una dimostrazione di base di JSON-B. Il listato 1 presenta il codice sorgente per questa demo.

Listato 1. JSONBDemo.java (versione 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()prima crea un Jsonboggetto seguito da un Employeeoggetto. Quindi chiama toJson()per serializzare l' Employeeoggetto in un documento JSON archiviato in una stringa. Dopo aver stampato questo documento, main()invoca fromJson()con la stringa precedente e Employeel' java.lang.Classoggetto di deserializzare il documento JSON su un altro Employeeoggetto, che viene successivamente stampato.

Il Listato 2 presenta Employeeil codice sorgente di.

Listato 2. Employee.java (versione 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(); } }

Compilare gli elenchi 1 e 2 come segue:

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

Eseguire l'applicazione come segue:

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

Tipi aggiuntivi come java.math.BigInteger, java.util.Datee java.time.LocalDatesono supportati. Controlla la specifica JSON-B per un elenco completo dei tipi supportati.

Serializzazione e deserializzazione di array e raccolte con JSON-B

La sezione precedente si è concentrata sulla serializzazione e deserializzazione di singoli oggetti Java. JSON-B supporta anche la possibilità di serializzare e deserializzare matrici e raccolte di oggetti. Il listato 3 fornisce una dimostrazione.

Listato 3. JSONBDemo.java (versione 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); } }

Il Listato 3 è una semplice estensione del Listato 1 e utilizza la stessa Employeeclasse presentata nel Listato 2. Inoltre, questo esempio di codice chiama gli stessi metodi toJson()e fromJson().