Introduzione all'API di associazione JSON (JSR 367) in Java

1. Panoramica

Per molto tempo non esisteva uno standard per l'elaborazione JSON in Java. Le librerie più comuni utilizzate per l'elaborazione JSON sono Jackson e Gson.

Recentemente, Java EE7 è stato fornito con un'API per l'analisi e la generazione di JSON (JSR 353: API Java per l'elaborazione JSON).

Infine, con il rilascio di JEE 8, è disponibile un'API standardizzata (JSR 367: Java API for JSON Binding (JSON-B)).

Per ora, le sue principali implementazioni sono Eclipse Yasson (RI) e Apache Johnzon.

2. API JSON-B

2.1. Dipendenza da Maven

Cominciamo aggiungendo la dipendenza necessaria.

Tieni presente che in molti casi sarà sufficiente includere la dipendenza per l'implementazione scelta e javax.json.bind-api verrà incluso in modo transitorio:

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

La versione più recente può essere trovata su Maven Central.

3. Utilizzo di Eclipse Yasson

Eclipse Yasson è l'implementazione di riferimento ufficiale di JSON Binding API (JSR-367).

3.1. Dipendenza da Maven

Per usarlo, dobbiamo includere le seguenti dipendenze nel nostro progetto Maven:

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

Le versioni più recenti possono essere trovate su Maven Central.

4. Utilizzo di Apache Johnzon

Un'altra implementazione che possiamo usare è Apache Johnzon che è conforme alle API JSON-P (JSR-353) e JSON-B (JSR-367).

4.1. Dipendenza da Maven

Per usarlo, dobbiamo includere le seguenti dipendenze nel nostro progetto Maven:

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

Le versioni più recenti possono essere trovate su Maven Central.

5. Funzionalità API

L'API fornisce annotazioni per personalizzare la serializzazione / deserializzazione.

Creiamo una semplice classe e vediamo come appare la configurazione di esempio:

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 }

Dopo la serializzazione, un oggetto di questa classe sarà simile a:

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

Le annotazioni qui utilizzate sono:

  • @JsonbProperty - che viene utilizzato per specificare un nome di campo personalizzato
  • @JsonbTransient - quando si desidera ignorare il campo durante la deserializzazione / serializzazione
  • @JsonbDateFormat - quando vogliamo definire il formato di visualizzazione della data
  • @JsonbNumberFormat - per specificare il formato di visualizzazione per i valori numerici
  • @JsonbNillable : per abilitare la serializzazione di valori null

5.1. Serializzazione e deserializzazione

Prima di tutto, per ottenere la rappresentazione JSON del nostro oggetto, dobbiamo utilizzare la classe JsonbBuilder e il suo metodo toJson () .

Per iniziare, creiamo un semplice oggetto Person come questo:

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

E, istanzia la classe Jsonb :

Jsonb jsonb = JsonbBuilder.create();

Quindi, usiamo il metodo toJson :

String jsonPerson = jsonb.toJson(person);

Per ottenere la seguente rappresentazione JSON:

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

Se vogliamo fare la conversione nell'altro modo, possiamo usare il metodo fromJson :

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

Naturalmente possiamo elaborare anche collezioni:

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

Per ottenere la seguente rappresentazione JSON:

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

Per convertire da un array JSON a List useremo l' API fromJson :

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

5.2. Mappatura personalizzata con JsonbConfig

La classe JsonbConfig ci consente di personalizzare il processo di mappatura per tutte le classi.

Ad esempio, possiamo modificare le strategie di denominazione predefinite o l'ordine delle proprietà.

Ora useremo la strategia LOWER_CASE_WITH_UNDERSCORES :

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

Per ottenere la seguente rappresentazione JSON:

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

Ora modificheremo l'ordine delle proprietà con la strategia REVERSE . Utilizzando questa strategia, l'ordine delle proprietà è in ordine inverso rispetto all'ordine lessicografico.

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.

Creiamo un PersonAdapter per elaborare gli attributi id e name della 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; } }

Inoltre, assegneremo l'adattatore alla nostra istanza JsonbConfig :

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

E otterremo la seguente rappresentazione JSON:

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

6. Conclusione

In questo tutorial, abbiamo visto un esempio di come integrare l'API JSON-B con le applicazioni Java utilizzando le implementazioni disponibili, insieme ad esempi di personalizzazione della serializzazione e deserializzazione sia a compilazione che a runtime.

Il codice completo è disponibile, come sempre, su Github.