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 .