Перейти к основному содержимому

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

· 5 мин. чтения

1. Обзор

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

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

И, наконец, с выпуском JEE 8 появился стандартизированный API ( JSR 367: Java API for JSON Binding (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":"jhon@test.com",
"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",
"jhon@test.com",
20,
LocalDate.of(2019, 9, 7),
BigDecimal.valueOf(1000));

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

Jsonb jsonb = JsonbBuilder.create();

Затем мы используем метод toJson :

String jsonPerson = jsonb.toJson(person);

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

{
"email":"jhon@test.com",
"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":"jhon@test.com",
"id":1,
"person-name":"Jhon",
"registeredDate":"09-09-2019",
"salary":"1000.0"
},
{
"email":"jhon1@test.com",
"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":"jhon@test.com",
"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":"jhon@test.com"
}

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

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

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

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

Давайте создадим 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 :

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

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

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

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

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

Полный код, как всегда, доступен на Github .