Рубрики
Без рубрики

Введение в Json iter

Узнайте, как анализировать JSON с помощью Json iter (json-итератор)

Автор оригинала: baeldung.

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:

  1. Мы начинаем с вызова метода readObject , который возвращает следующее имя поля (или null , если достигнут конец документа).
  2. Если имя поля нас не интересует, мы пропускаем элемент JSON с помощью метода skip . В противном случае мы проверяем тип данных элемента с помощью метода what Is Next . Вызов метода whatIsNext не является обязательным, но полезен, когда тип данных поля нам неизвестен.
  3. Наконец, мы извлекаем значение элемента JSON с помощью метода ReadString .

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

В этой статье мы обсудили различные подходы, предлагаемые Json iter для анализа документов JSON как объектов Java.

Во-первых, мы рассмотрели стандартный способ анализа документа JSON с использованием класса схемы.

Затем мы рассмотрели обработку нечетких типов данных и динамических структур при анализе документов JSON с использованием декодеров Maybe и Любого типа данных соответственно.

Наконец, мы рассмотрели API Iterator для привязки JSON вручную к объекту Java.

Как всегда, исходный код для примеров, используемых в этой статье, доступен на GitHub .