Java XML et JSON: traitement de documents pour Java SE, partie 2: JSON-B

Dans cet article, nous allons continuer à explorer XML et JSON dans Java 11 et au-delà.

Les exemples de cet article vous présenteront JSON-B, l'API de liaison JSON pour Java. Après une présentation rapide et des instructions d'installation, je vais vous montrer comment utiliser JSON-B pour sérialiser et désérialiser des objets, des tableaux et des collections Java; comment personnaliser la sérialisation et la désérialisation à l'aide de JSON-B; et comment utiliser des adaptateurs JSON-B pour convertir des objets source en objets cible pendant la sérialisation ou la désérialisation.

Le contenu de cet article est complètement nouveau, mais pourrait être considéré comme un chapitre supplémentaire (chapitre 13) pour mon nouveau livre, récemment publié par Apress: Java XML et JSON, deuxième édition .

À propos du livre: Java XML et JSON

Comme je l'ai partagé dans mon précédent article, Apress vient de publier la deuxième édition de mon livre, Java XML et JSON . Ce fut un plaisir d'écrire un livre entier sur XML et JSON, deux technologies que je considère plus complémentaires que compétitives. Après la publication du livre, j'ai ajouté de nouveaux exemples pour le chapitre 6: Transformer des documents XML avec XSLT et pour le chapitre 11: Traitement JSON avec Jackson. Mon dernier article, "Java XML et JSON: traitement de documents pour Java SE, partie 1" a présenté une variété de techniques de transformation et de traitement de documents utilisant SAXON et Jackson. N'oubliez pas de consulter cet article pour en savoir plus sur ces techniques.

Obtenez le code

Téléchargez le code source des exemples utilisés dans ce didacticiel.

Qu'est-ce que JSON-B?

JSON-B est une couche de liaison standard et une API pour la conversion d'objets Java vers et à partir de documents JSON. Il est similaire à Java Architecture for XML Binding (JAXB), qui est utilisé pour convertir des objets Java vers et depuis XML.

JSON-B repose sur JSON-P, l'API de traitement JSON utilisée pour analyser, générer, interroger et transformer des documents JSON. JSON-B a été introduit par Java Specification Request (JSR) 367 plus d'un an après la version finale de JSR 353, le JSR pour JSON-P.

L'API JSON-B

Le site Web de l'API Java pour la liaison JSON (JSON-B) présente JSON-B et permet d'accéder à diverses ressources, y compris la documentation de l'API. Selon la documentation, le module JSON-B stocke six packages:

  • javax.json.bind: Définit le point d'entrée pour la liaison des objets Java aux documents JSON.
  • javax.json.bind.adapter: Définit les classes liées à l'adaptateur.
  • javax.json.bind.annotation: Définit des annotations pour personnaliser le mappage entre les éléments de programme Java et les documents JSON.
  • javax.json.bind.config: Définit des stratégies et des politiques pour personnaliser le mappage entre les éléments de programme Java et les documents JSON.
  • javax.json.bind.serializer: Définit les interfaces pour créer des sérialiseurs et des désérialiseurs personnalisés.
  • javax.json.bind.spi: Définit une interface de fournisseur de services (SPI) pour brancher des JsonbBuilders personnalisés .

Le site Web JSON-B fournit également un lien vers Yasson, un framework Java qui fournit une couche de liaison standard entre les classes Java et les documents JSON, et une implémentation de référence officielle de l'API de liaison JSON.

JSON-B et Java EE 8

Comme JSON-P, JSON-B a été initialement envisagé pour être inclus dans Java SE, mais a été inclus dans la version Java EE 8 à la place. Cependant, vous pouvez toujours travailler avec JSON-B dans un contexte Java SE.

Téléchargez et installez JSON-B

JSON-B 1.0 est la version actuelle au moment de la rédaction. Vous pouvez obtenir l'implémentation de référence Yasson de cette bibliothèque à partir du référentiel Maven. Vous devrez télécharger les fichiers JAR suivants:

  • Javax JSON Bind API 1.0: contient tous les fichiers de classe JSON-B. J'ai téléchargé javax.json.bind-api-1.0.jar.
  • Yasson: contient l'implémentation de référence basée sur Eclipse de JSON-B. J'ai téléchargé yasson-1.0.3.jar.
  • Fournisseur par défaut JSR 374 (traitement JSON): contient tous les fichiers de classe JSON-P 1.0 ainsi que les fichiers de classe du fournisseur par défaut de Glassfish. J'ai téléchargé javax.json-1.1.4.jar.

Ajoutez ces fichiers JAR à votre chemin de classe lors de la compilation et de l'exécution de code utilisant ces bibliothèques:

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

Sérialisation et désérialisation d'objets Java avec JSON-B

Le javax.json.bindpackage fournit les interfaces Jsonbet JsonbBuilder, qui servent de point d'entrée à cette bibliothèque:

  • Jsonbfournit des toJson()méthodes surchargées pour la sérialisation des arborescences d'objets Java en documents JSON et des fromJson()méthodes pour désérialiser des documents JSON en arborescences d'objets Java.
  • JsonbBuilderfournit newBuilder()et d'autres méthodes pour obtenir un nouveau générateur, et build()et des create()méthodes pour renvoyer de nouveaux Jsonbobjets.

L'exemple de code suivant illustre l'utilisation de base des types Jsonbet 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);

Cet exemple appelle Jsonbla String toJson(Object object)méthode de pour sérialiser un objet Java, ( Employee). Cette méthode reçoit la racine de l'arborescence d'objets Java pour sérialiser. Si nullest passé, toJson()jette java.lang.NullPointerException. Il se déclenche javax.json.bind.JsonbExceptionlorsqu'un problème inattendu (tel qu'une erreur d'E / S) se produit pendant la sérialisation.

Ce fragment de code appelle également Jsonbla T fromJson(String str, Class type)méthode générique de, qui est utilisée pour la désérialisation. Cette méthode reçoit le document JSON basé sur une chaîne à désérialiser et le type de l'objet racine de l'arborescence d'objets Java résultant, qui est retourné. Cette méthode renvoie NullPointerExceptionquand nullest passé à l'un ou l'autre des paramètres; il lève JsonbExceptionlorsqu'un problème inattendu se produit lors de la désérialisation.

J'ai extrait le fragment de code d'une JSONBDemoapplication qui fournit une démonstration de base de JSON-B. Le listing 1 présente le code source de cette démo.

Liste 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()crée d'abord un Jsonbobjet suivi d'un Employeeobjet. Il appelle ensuite toJson()à sérialiser l' Employeeobjet dans un document JSON stocké dans une chaîne. Après avoir imprimé ce document, main()invoque fromJson()avec la chaîne précédente et Employeel' java.lang.Classobjet de pour désérialiser le document JSON en un autre Employeeobjet, qui est ensuite imprimé.

Le listing 2 présente Employeele code source de.

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

Compilez les listes 1 et 2 comme suit:

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

Exécutez l'application comme suit:

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

D' autres types tels que java.math.BigInteger, java.util.Dateet java.time.LocalDatesont pris en charge. Consultez la spécification JSON-B pour une liste complète des types pris en charge.

Sérialisation et désérialisation de tableaux et de collections avec JSON-B

La section précédente s'est concentrée sur la sérialisation et la désérialisation d'objets Java uniques. JSON-B prend également en charge la possibilité de sérialiser et de désérialiser des tableaux et des collections d'objets. Le listing 3 en fournit une démonstration.

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

Le Listing 3 est une simple extension du Listing 1, et utilise la même Employeeclasse présentée dans le Listing 2. En outre, cet exemple de code appelle les mêmes méthodes toJson()et fromJson().