«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 с использованием доступных реализаций, а также примеры настройки сериализации и десериализации как во время компиляции, так и во время выполнения.