Introduction à l'API de liaison JSON (JSR 367) en Java

1. Vue d'ensemble

Pendant longtemps, il n'y avait pas de standard pour le traitement JSON en Java. Les bibliothèques les plus couramment utilisées pour le traitement JSON sont Jackson et Gson.

Récemment, Java EE7 est venu avec une API pour l'analyse et la génération de JSON (JSR 353: API Java pour le traitement JSON).

Et enfin, avec la sortie de JEE 8, il existe une API standardisée (JSR 367: Java API for JSON Binding (JSON-B)).

Pour l'instant, ses principales implémentations sont Eclipse Yasson (RI) et Apache Johnzon.

2. API JSON-B

2.1. Dépendance de Maven

Commençons par ajouter la dépendance nécessaire.

Gardez à l'esprit que dans de nombreux cas, il suffira d'inclure la dépendance de l'implémentation choisie et javax.json.bind-api sera inclus de manière transitoire:

 javax.json.bind javax.json.bind-api 1.0 

La version la plus récente est disponible sur Maven Central.

3. Utilisation d'Eclipse Yasson

Eclipse Yasson est l'implémentation de référence officielle de l'API de liaison JSON (JSR-367).

3.1. Dépendance de Maven

Pour l'utiliser, nous devons inclure les dépendances suivantes dans notre projet Maven:

 org.eclipse yasson 1.0.1   org.glassfish javax.json 1.1.2 

Les versions les plus récentes sont disponibles sur Maven Central.

4. Utilisation d'Apache Johnzon

Une autre implémentation que nous pouvons utiliser est Apache Johnzon qui est conforme aux API JSON-P (JSR-353) et JSON-B (JSR-367).

4.1. Dépendance de Maven

Pour l'utiliser, nous devons inclure les dépendances suivantes dans notre projet Maven:

 org.apache.geronimo.specs geronimo-json_1.1_spec 1.0   org.apache.johnzon johnzon-jsonb 1.1.4 

Les versions les plus récentes sont disponibles sur Maven Central.

5. Fonctionnalités de l'API

L'API fournit des annotations pour personnaliser la sérialisation / désérialisation.

Créons une classe simple et voyons à quoi ressemble l'exemple de configuration:

public class Person { private int id; @JsonbProperty("person-name") private String name; @JsonbProperty(nillable = true) private String email; @JsonbTransient private int age; @JsonbDateFormat("dd-MM-yyyy") private LocalDate registeredDate; private BigDecimal salary; @JsonbNumberFormat(locale = "en_US", value = "#0.0") public BigDecimal getSalary() { return salary; } // standard getters and setters }

Après la sérialisation, un objet de cette classe ressemblera à:

{ "email":"[email protected]", "id":1, "person-name":"Jhon", "registeredDate":"07-09-2019", "salary":"1000.0" }

Les annotations utilisées ici sont:

  • @JsonbProperty - qui est utilisé pour spécifier un nom de champ personnalisé
  • @JsonbTransient - lorsque nous voulons ignorer le champ lors de la désérialisation / sérialisation
  • @JsonbDateFormat - quand on veut définir le format d'affichage de la date
  • @JsonbNumberFormat - pour spécifier le format d'affichage des valeurs numériques
  • @JsonbNillable - pour activer la sérialisation des valeurs nulles

5.1. Sérialisation et désérialisation

Tout d'abord, pour obtenir la représentation JSON de notre objet, nous devons utiliser la classe JsonbBuilder et sa méthode toJson () .

Pour commencer, créons un objet Person simple comme celui-ci:

Person person = new Person( 1, "Jhon", "[email protected]", 20, LocalDate.of(2019, 9, 7), BigDecimal.valueOf(1000));

Et instanciez la classe Jsonb :

Jsonb jsonb = JsonbBuilder.create();

Ensuite, nous utilisons la méthode toJson :

String jsonPerson = jsonb.toJson(person);

Pour obtenir la représentation JSON suivante:

{ "email":"[email protected]", "id":1, "person-name":"Jhon", "registeredDate":"07-09-2019", "salary":"1000.0" }

Si nous voulons faire la conversion dans l'autre sens, nous pouvons utiliser la méthode fromJson :

Person person = jsonb.fromJson(jsonPerson, Person.class);

Naturellement, nous pouvons également traiter des collections:

List personList = Arrays.asList(...); String jsonArrayPerson = jsonb.toJson(personList);

Pour obtenir la représentation JSON suivante:

[ { "email":"[email protected]", "id":1, "person-name":"Jhon", "registeredDate":"09-09-2019", "salary":"1000.0" }, { "email":"[email protected]", "id":2, "person-name":"Jhon", "registeredDate":"09-09-2019", "salary":"1500.0" }, ... ]

Pour convertir un tableau JSON en liste, nous utiliserons l' API fromJson :

List personList = jsonb.fromJson( personJsonArray, new ArrayList(){}.getClass().getGenericSuperclass() );

5.2. Mappage personnalisé avec JsonbConfig

La classe JsonbConfig nous permet de personnaliser le processus de mappage pour toutes les classes.

Par exemple, nous pouvons modifier les stratégies de dénomination par défaut ou l'ordre des propriétés.

Nous allons maintenant utiliser la stratégie LOWER_CASE_WITH_UNDERSCORES :

JsonbConfig config = new JsonbConfig().withPropertyNamingStrategy( PropertyNamingStrategy.LOWER_CASE_WITH_UNDERSCORES); Jsonb jsonb = JsonbBuilder.create(config); String jsonPerson = jsonb.toJson(person);

Pour obtenir la représentation JSON suivante:

{ "email":"[email protected]", "id":1, "person-name":"Jhon", "registered_date":"07-09-2019", "salary":"1000.0" }

Maintenant, nous allons changer l'ordre des propriétés avec la stratégie REVERSE . En utilisant cette stratégie, l'ordre des propriétés est dans l'ordre inverse de l'ordre lexicographique.

This can also be configured at compile time with the annotation @JsonbPropertyOrder. Let’s see it in action:

JsonbConfig config = new JsonbConfig().withPropertyOrderStrategy(PropertyOrderStrategy.REVERSE); Jsonb jsonb = JsonbBuilder.create(config); String jsonPerson = jsonb.toJson(person); 

To obtain the following JSON representation:

{ "salary":"1000.0", "registeredDate":"07-09-2019", "person-name":"Jhon", "id":1, "email":"[email protected]" }

5.3. Custom Mapping With Adapters

When the annotations and the JsonbConfig class aren’t enough for us, we can use adapters.

To use them, we’ll need to implement the JsonbAdapter interface, which defines the following methods:

  • adaptToJson – With this method, we can use custom conversion logic for the serialization process.
  • adaptFromJson – This method allows us to use custom conversion logic for the deserialization process.

Créons un PersonAdapter pour traiter les attributs id et name de la classe Person :

public class PersonAdapter implements JsonbAdapter { @Override public JsonObject adaptToJson(Person p) throws Exception { return Json.createObjectBuilder() .add("id", p.getId()) .add("name", p.getName()) .build(); } @Override public Person adaptFromJson(JsonObject adapted) throws Exception { Person person = new Person(); person.setId(adapted.getInt("id")); person.setName(adapted.getString("name")); return person; } }

De plus, nous attribuerons l'adaptateur à notre instance JsonbConfig :

JsonbConfig config = new JsonbConfig().withAdapters(new PersonAdapter()); Jsonb jsonb = JsonbBuilder.create(config);

Et nous obtiendrons la représentation JSON suivante:

{ "id":1, "name":"Jhon" }

6. Conclusion

Dans ce didacticiel, nous avons vu un exemple d'intégration de l'API JSON-B avec des applications Java à l'aide des implémentations disponibles, ainsi que des exemples de personnalisation de la sérialisation et de la désérialisation à la fois à la compilation et à l'exécution.

Le code complet est disponible, comme toujours, sur Github.