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 .