1. введение
Нотация объектов JavaScript, или JSON, в последние годы приобрела большую популярность в качестве формата обмена данными. Json iter – это новая библиотека синтаксического анализа JSON, предназначенная для обеспечения более гибкого и более эффективного синтаксического анализа JSON, чем другие доступные анализаторы.
В этом уроке мы увидим, как анализировать объекты JSON с помощью библиотеки Json iter для Java.
2. Зависимости
Последнюю версию Json iter можно найти в центральном репозитории Maven.
Давайте начнем с добавления зависимостей в pom.xml :
com.jsoniter jsoniter 0.9.23
Аналогично, мы можем добавить зависимость в наш файл build.gradle :
compile group: 'com.jsoniter', name: 'jsoniter', version: '0.9.23'
3. Синтаксический анализ JSON С использованием Json iter
Json iter предоставляет 3 API для анализа документов JSON:
- Привязка API
- Любой API
- API итератора
Давайте рассмотрим каждый из вышеперечисленных API.
3.1. Синтаксический анализ JSON с использованием Bind API
API привязки использует традиционный способ привязки документа JSON к классам Java.
Давайте рассмотрим документ JSON с подробными сведениями о студенте:
{"id":1,"name":{"firstName":"Joe","surname":"Blogg"}}Теперь давайте определим классы Student и Name schema для представления вышеуказанного JSON:
public class Student {
private int id;
private Name name;
// standard setters and getters
}public class Name {
private String firstName;
private String surname;
// standard setters and getters
}Де-сериализация JSON в объект Java с помощью API привязки очень проста. Мы используем десериализуем метод JsonIterator :
@Test
public void whenParsedUsingBindAPI_thenConvertedToJavaObjectCorrectly() {
String input = "{\"id\":1,\"name\":{\"firstName\":\"Joe\",\"surname\":\"Blogg\"}}";
Student student = JsonIterator.deserialize(input, Student.class);
assertThat(student.getId()).isEqualTo(1);
assertThat(student.getName().getFirstName()).isEqualTo("Joe");
assertThat(student.getName().getSurname()).isEqualTo("Blogg");
}Класс Student schema объявляет id принадлежащим int типу данных . Однако, что делать, если JSON, который мы получаем, содержит Строку значение для id вместо числа? Например:
{"id":"1","name":{"firstName":"Joe","surname":"Blogg"}}Обратите внимание, что на этот раз id в JSON является строковым значением “1” . Json iter предоставляет Возможно декодеры для работы с этим сценарием.
3.2. Возможно, Декодеры
Декодеры Jsoniter Возможно пригодятся, когда тип данных элемента JSON нечеткий . Тип данных для student.id поле нечеткое — это может быть либо Строка , либо int . Чтобы справиться с этим, нам нужно аннотировать поле id в вашем классе схемы с помощью декодера Maybe String Int :
public class Student {
@JsonProperty(decoder = MaybeStringIntDecoder.class)
private int id;
private Name name;
// standard setters and getters
}
Теперь мы можем анализировать JSON, даже если значение id является строкой :
@Test
public void givenTypeInJsonFuzzy_whenFieldIsMaybeDecoded_thenFieldParsedCorrectly() {
String input = "{\"id\":\"1\",\"name\":{\"firstName\":\"Joe\",\"surname\":\"Blogg\"}}";
Student student = JsonIterator.deserialize(input, Student.class);
assertThat(student.getId()).isEqualTo(1);
}Аналогично, Json iter предлагает другие декодеры, такие как Может Быть, Декодер С Длинной Строкой и Может быть Декодер пустого массива .
Давайте теперь представим, что мы ожидали получить документ JSON с деталями Student , но вместо этого мы получили следующий документ:
{"error":404,"description":"Student record not found"}
Что здесь произошло? Мы ожидали успешного ответа с данными Student , но получили ответ error . Это очень распространенный сценарий, но как бы мы с этим справились?
Один из способов-выполнить проверку null , чтобы проверить, получили ли мы ответ на ошибку, прежде чем извлекать данные Student . Однако проверки null могут привести к некоторому трудночитаемому коду, и проблема усугубляется, если у нас есть многоуровневый вложенный JSON.
На помощь приходит синтаксический анализ Jsoniter с использованием Любого API.
3.3. Синтаксический анализ JSON С использованием любого API
Когда сама структура JSON динамична, мы можем использовать Любой API Jsoniter, который обеспечивает анализ JSON без схемы . Это работает аналогично разбору JSON в Map Object> . Object>
Давайте разберем Student JSON, как и раньше, но на этот раз с помощью Любого API:
@Test
public void whenParsedUsingAnyAPI_thenFieldValueCanBeExtractedUsingTheFieldName() {
String input = "{\"id\":1,\"name\":{\"firstName\":\"Joe\",\"surname\":\"Blogg\"}}";
Any any = JsonIterator.deserialize(input);
assertThat(any.toInt("id")).isEqualTo(1);
assertThat(any.toString("name", "firstName")).isEqualTo("Joe");
assertThat(any.toString("name", "surname")).isEqualTo("Blogg");
}Давайте разберемся в этом примере. Во-первых, мы используем JsonIterator.deserialize(..) для анализа JSON. Однако мы не указываем класс схемы в этом экземпляре. Результат имеет тип Any.
Затем мы читаем значения полей, используя имена полей. Мы считываем значение поля “id” с помощью метода Any.toInt . Метод toInt преобразует значение “id” в целое число. Аналогично, мы читаем значения полей “имя.Имя” и “имя.фамилия” как строковые значения, используя метод toString .
Использование Любого API, мы также можем проверить, присутствует ли элемент в JSON. Мы можем сделать это, посмотрев на элемент, а затем проверив Тип значения результата поиска. Тип значения будет НЕДОПУСТИМЫМ , если элемент отсутствует в JSON.
Например:
@Test
public void whenParsedUsingAnyAPI_thenFieldValueTypeIsCorrect() {
String input = "{\"id\":1,\"name\":{\"firstName\":\"Joe\",\"surname\":\"Blogg\"}}";
Any any = JsonIterator.deserialize(input);
assertThat(any.get("id").valueType()).isEqualTo(ValueType.NUMBER);
assertThat(any.get("name").valueType()).isEqualTo(ValueType.OBJECT);
assertThat(any.get("error").valueType()).isEqualTo(ValueType.INVALID);
}Поля “id” и “name” присутствуют в JSON, и, следовательно, их Тип значения является НОМЕРОМ и ОБЪЕКТОМ соответственно. Однако входные данные JSON не содержат элемента с именем “error”, поэтому тип value является НЕДОПУСТИМЫМ .
Возвращаясь к сценарию, упомянутому в конце предыдущего раздела, нам нужно определить, является ли полученный нами ввод JSON успешным или ответом на ошибку. Мы можем проверить, получили ли мы ответ на ошибку, проверив ValueType элемента “error”:
String input = "{\"error\":404,\"description\":\"Student record not found\"}";
Any response = JsonIterator.deserialize(input);
if (response.get("error").valueType() != ValueType.INVALID) {
return "Error!! Error code is " + response.toInt("error");
}
return "Success!! Student id is " + response.toInt("id");При запуске приведенный выше код вернет “Ошибка!! Код ошибки-404” .
Далее мы рассмотрим использование API итератора для анализа документов JSON.
3.4. Синтаксический анализ JSON С использованием API итератора
Если мы хотим выполнить привязку вручную, мы можем использовать Json iter Iterator API. Давайте рассмотрим JSON:
{"firstName":"Joe","surname":"Blogg"}Мы будем использовать класс Name schema, который мы использовали ранее, для анализа JSON с помощью Итератора API:
@Test
public void whenParsedUsingIteratorAPI_thenFieldValuesExtractedCorrectly() throws Exception {
Name name = new Name();
String input = "{\"firstName\":\"Joe\",\"surname\":\"Blogg\"}";
JsonIterator iterator = JsonIterator.parse(input);
for (String field = iterator.readObject(); field != null; field = iterator.readObject()) {
switch (field) {
case "firstName":
if (iterator.whatIsNext() == ValueType.STRING) {
name.setFirstName(iterator.readString());
}
continue;
case "surname":
if (iterator.whatIsNext() == ValueType.STRING) {
name.setSurname(iterator.readString());
}
continue;
default:
iterator.skip();
}
}
assertThat(name.getFirstName()).isEqualTo("Joe");
assertThat(name.getSurname()).isEqualTo("Blogg");
}Давайте разберемся в приведенном выше примере. Во-первых, мы анализируем документ JSON в качестве итератора. Мы используем полученный экземпляр JsonIterator для перебора элементов JSON:
- Мы начинаем с вызова метода readObject , который возвращает следующее имя поля (или null , если достигнут конец документа).
- Если имя поля нас не интересует, мы пропускаем элемент JSON с помощью метода skip . В противном случае мы проверяем тип данных элемента с помощью метода what Is Next . Вызов метода whatIsNext не является обязательным, но полезен, когда тип данных поля нам неизвестен.
- Наконец, мы извлекаем значение элемента JSON с помощью метода ReadString .
4. Заключение
В этой статье мы обсудили различные подходы, предлагаемые Json iter для анализа документов JSON как объектов Java.
Во-первых, мы рассмотрели стандартный способ анализа документа JSON с использованием класса схемы.
Затем мы рассмотрели обработку нечетких типов данных и динамических структур при анализе документов JSON с использованием декодеров Maybe и Любого типа данных соответственно.
Наконец, мы рассмотрели API Iterator для привязки JSON вручную к объекту Java.
Как всегда, исходный код для примеров, используемых в этой статье, доступен на GitHub .