«1. Обзор

Долгое время в Java не существовало стандарта для обработки JSON. Наиболее распространенными библиотеками, используемыми для обработки JSON, являются Jackson и Gson.

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

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

На данный момент его основными реализациями являются Eclipse Yasson (RI) и Apache Johnzon.

2. JSON-B API

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

Давайте начнем с добавления необходимой зависимости.

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

<dependency>
    <groupId>javax.json.bind</groupId>
    <artifactId>javax.json.bind-api</artifactId>
    <version>1.0</version>
</dependency>

Самая последняя версия может быть найдена в Maven Central.

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

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

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

Чтобы использовать ее, нам нужно включить следующие зависимости в наш проект Maven:

<dependency>
    <groupId>org.eclipse</groupId>
    <artifactId>yasson</artifactId>
    <version>1.0.1</version>
</dependency>
<dependency>
    <groupId>org.glassfish</groupId>
    <artifactId>javax.json</artifactId>
    <version>1.1.2</version>
</dependency>

Самые последние версии можно найти на Maven Central.

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

Другая реализация, которую мы можем использовать, — это Apache Johnzon, который соответствует API JSON-P (JSR-353) и JSON-B (JSR-367).

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

Чтобы использовать ее, нам нужно включить следующие зависимости в наш проект Maven:

<dependency>
    <groupId>org.apache.geronimo.specs</groupId>
    <artifactId>geronimo-json_1.1_spec</artifactId>
    <version>1.0</version>
</dependency>
<dependency>
    <groupId>org.apache.johnzon</groupId>
    <artifactId>johnzon-jsonb</artifactId>
    <version>1.1.4</version>
</dependency>

Самые последние версии можно найти на 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<Person> 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<Person> personList = jsonb.fromJson(
  personJsonArray, 
  new ArrayList<Person>(){}.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. При использовании этой стратегии порядок свойств находится в порядке, обратном лексикографическому порядку. Это также можно настроить во время компиляции с помощью аннотации @JsonbPropertyOrder. Давайте посмотрим на это в действии:


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

Чтобы получить следующее представление JSON:

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

5.3. Пользовательское сопоставление с адаптерами

Когда аннотаций и класса JsonbConfig нам недостаточно, мы можем использовать адаптеры.

Чтобы использовать их, нам нужно реализовать интерфейс JsonbAdapter, который определяет следующие методы:

    adaptToJson — с помощью этого метода мы можем использовать пользовательскую логику преобразования для процесса сериализации. adaptFromJson — этот метод позволяет нам использовать пользовательскую логику преобразования для процесса десериализации.

Давайте создадим PersonAdapter для обработки атрибутов id и name класса Person:

public class PersonAdapter implements JsonbAdapter<Person, JsonObject> {

    @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 config = new JsonbConfig().withAdapters(new PersonAdapter());
Jsonb jsonb = JsonbBuilder.create(config);

«Кроме того, мы назначим адаптер нашему экземпляру JsonbConfig:

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

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

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

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