Въведение в JSON Binding API (JSR 367) в Java

1. Общ преглед

Дълго време в Java нямаше стандарт за JSON обработка. Най-често използваните библиотеки, използвани за обработка на JSON, са Jackson и Gson.

Наскоро Java EE7 дойде с API за анализиране и генериране на JSON (JSR 353: Java API за обработка на JSON).

И накрая, с пускането на JEE 8 има стандартизиран API (JSR 367: Java API за JSON Binding (JSON-B)).

Засега основните му внедрения са Eclipse Yasson (RI) и Apache Johnzon.

2. JSON-B API

2.1. Зависимост на Maven

Нека започнем с добавяне на необходимата зависимост.

Имайте предвид, че в много случаи ще е достатъчно да включите зависимостта за избраната реализация и javax.json.bind-api ще бъде включен преходно:

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

Най-новата версия може да бъде намерена в Maven Central.

3. Използване на Eclipse Yasson

Eclipse Yasson е официалната референтна реализация на JSON Binding API (JSR-367).

3.1. Зависимост на Maven

За да го използваме, трябва да включим следните зависимости в нашия проект Maven:

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

Най-новите версии могат да бъдат намерени в Maven Central.

4. Използване на Apache Johnzon

Друго внедряване, което можем да използваме, е Apache Johnzon, което е в съответствие с JSON-P (JSR-353) и JSON-B (JSR-367) API.

4.1. Зависимост на Maven

За да го използваме, трябва да включим следните зависимости в нашия проект Maven:

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

Най-новите версии могат да бъдат намерени в Maven Central.

5. Функции на API

API предоставя анотации за персонализиране на сериализация / десериализация.

Нека създадем прост клас и да видим как изглежда примерната конфигурация:

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 }

След сериализацията обект от този клас ще изглежда така:

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

Анотациите, използвани тук, са:

  • @JsonbProperty - който се използва за посочване на име на персонализирано поле
  • @JsonbTransient - когато искаме да игнорираме полето по време на десериализация / сериализация
  • @JsonbDateFormat - когато искаме да определим формата на показване на датата
  • @JsonbNumberFormat - за определяне на формата на дисплея за числови стойности
  • @JsonbNillable - за разрешаване на сериализация на нулеви стойности

5.1. Сериализация и десериализация

На първо място, за да получим JSON представяне на нашия обект, трябва да използваме класа JsonbBuilder и неговия метод toJson () .

За начало нека създадем прост обект Person като този:

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

И създайте екземпляр на класа Jsonb :

Jsonb jsonb = JsonbBuilder.create();

След това използваме метода toJson :

String jsonPerson = jsonb.toJson(person);

За да получите следното представяне на JSON:

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

Ако искаме да направим преобразуването по друг начин, можем да използваме метода fromJson :

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

Естествено, можем да обработваме и колекции:

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

За да получите следното представяне на 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" }, ... ]

За да конвертираме от JSON масив в Списък , ще използваме API на fromJson :

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

5.2. Персонализирано картографиране с JsonbConfig

Класът JsonbConfig ни позволява да персонализираме процеса на картографиране за всички класове.

Например можем да променим стратегиите за именуване по подразбиране или реда на свойствата.

Сега ще използваме стратегията LOWER_CASE_WITH_UNDERSCORES :

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

За да получите следното представяне на JSON:

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

Сега ще променим реда на собствеността със стратегията REVERSE . Използвайки тази стратегия, редът на свойствата е в обратен ред от лексикографския.

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.

Нека създадем PersonAdapter за обработка на атрибутите id и name на класа 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; } }

Освен това ще присвоим адаптера на нашия екземпляр JsonbConfig :

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

И ще получим следното представяне на JSON:

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

6. Заключение

В този урок видяхме пример за това как да интегрираме JSON-B API с Java приложения, използвайки наличните реализации, заедно с примери за персонализиране на сериализация и десериализация както при компилиране, така и по време на изпълнение.

Пълният код е достъпен, както винаги, в Github.