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

Получить список объектов JSON с WebClient

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

1. Обзор

Наши службы часто общаются с другими службами REST для получения информации.

С 5 весны мы будем пользоваться WebClient для выполнения этих запросов реактивным, не блокирующим способом. WebClient является частью новой WebFlux Рамки, построенные поверх Проект Реактор . Он имеет беглый, реактивный API, и он использует протокол HTTP в своей основной реализации.

Когда мы делаем веб-запрос, данные часто возвращаются как JSON. WebClient может преобразовать это для нас.

В этой статье мы узнаем, как преобразовать JSON Array в java- Массив Объект , Массив POJO , и Список POJO с использованием WebClient .

2. Зависимости

Использовать WebClient, Нам нужно добавить пару зависимостей к нашему пом.xml:


    org.springframework.boot
    spring-boot-starter-webflux


    org.projectreactor
    reactor-spring
    1.0.1.RELEASE

3. JSON, POJO, и обслуживание

Начнем с конечной точки http://localhost:8080/readers , который возвращает список читателей с их любимыми книгами, как массив JSON:

[{
    "id": 1,
    "name": "reader1",
    "favouriteBook": { 
        "author": "Milan Kundera",
        "title": "The Unbearable Lightness of Being"
    }
}, {
    "id": 2,
    "name": "reader2"
    "favouriteBook": { 
        "author": "Douglas Adams",
        "title": "The Hitchhiker's Guide to the Galaxy"
    }
}]

Мы будем требовать соответствующей Читатель и Книжный классы для обработки данных:

public class Reader {
    private int id;
    private String name;
    private Book favouriteBook;

    // getters and setters..
}
public class Book {
    private final String author;
    private final String title;

   // getters and setters..
}

Для реализации интерфейса мы пишем ReaderConsumerServiceImpl с WebClient как его зависимость:

public class ReaderConsumerServiceImpl implements ReaderConsumerService {

    private final WebClient webClient;

    public ReaderConsumerServiceImpl(WebClient webclient) {
        this.webclient = webclient;
    }

    // ...
}

4. Сопоставление списка объектов JSON

Когда мы получаем массив JSON по запросу REST, существует несколько способов преобразовать его в коллекцию Java. Давайте рассмотрим различные варианты и посмотрим, как легко обработать возвращенные данные. Мы посмотрим на извлечение любимых книг читателей.

4.1. Моно vs. Флюкс

Проект Реактор ввела две реализации Издатель: Моно и Флюс .

Flux полезно, когда нам нужно обрабатывать ноль для многих или потенциально бесконечных результатов. В качестве примера можно привести ленту Twitter.

Когда мы знаем, что результаты возвращаются все сразу – как и в нашем случае использования – мы можем использовать Моно .

4.2. WebClient с объектом Array

Во-первых, давайте ПОЛУЧИТЬ звонок с WebClient.get и использовать Моно типа Объект для сбора ответа:

Mono response = webClient.get()
  .accept(MediaType.APPLICATION_JSON)
  .retrieve()
  .bodyToMono(Object[].class).log();

Далее, давайте извлекаем тело в наш массив Объект :

Object[] objects = response.block();

Фактическое Объект вот произвольная структура, которая содержит наши данные. Давайте преобразуем его в массив Читатель Объектов.

Для этого нам понадобится ОбъектМаппер :

ObjectMapper mapper = new ObjectMapper();

Здесь мы объявили его в ряд, хотя это обычно делается как частные статические окончательные член класса.

Наконец, мы готовы извлечь любимые книги читателей и собрать их в список:

return Arrays.stream(objects)
  .map(object -> mapper.convertValue(object, Reader.class))
  .map(Reader::getFavouriteBook)
  .collect(Collectors.toList());

Когда мы спрашиваем Джексон deserializer производить Объект в качестве целевого типа, он на самом деле deserializes JSON в серии LinkedHashMap объекты . После обработки с конвертироватьВалю является неэффективным. Мы можем избежать этого, если мы предоставляем наш желаемый тип Джексона во время deserialization.

4.3. WebClient с Reader Array

Мы можем предоставить Читатель вместо Объект к нашему WebClient :

Mono response = webClient.get()
  .accept(MediaType.APPLICATION_JSON)
  .retrieve()
  .bodyToMono(Reader[].class).log();
Reader[] readers = response.block();
return Arrays.stream(readers)
  .map(Reader:getFavouriteBook)
  .collect(Collectors.toList());

Здесь мы можем заметить, что нам больше не нужна ObjectMapper.convertValue . Тем не менее, нам все еще нужно сделать дополнительные преобразования, чтобы использовать Java Поток API и для работы нашего кода с Список .

4.4. WebClient со списком читателей

Если мы хотим, чтобы Джексон Список Читатель s вместо массива, мы должны описать Список мы хотим творить. Для этого мы предоставляем Параметризированный ТипРеференс производства анонимный внутренний класс к методу:

Mono response = webClient.get()
  .accept(MediaType.APPLICATION_JSON)
  .retrieve()
  .bodyToMono(new ParameterizedTypeReference() {});
List readers = response.block();

return readers.stream()
  .map(Reader::getFavouriteBook)
  .collect(Collectors.toList());

Это дает нам Список с чем мы можем работать.

Давайте глубже погрузимся в почему мы должны использовать Параметризированный ТипРеференс .

Spring’s WebClient может легко deserialize JSON в Читатель.class когда информация о типе доступна во время выполнения.

С дженериками, однако, тип стирания происходит, если мы пытаемся использовать Список.class . Таким образом, Джексон не сможет определить параметр типа дженерика.

Используя Параметризированный ТипРеференс , мы можем преодолеть эту проблему. Мгновенное использование его как анонимного внутреннего класса использует тот факт, что подклассы общих классов содержат информацию типа компиляции времени, которая не подлежит стирания типа и может потребляться через отражение.

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

В этом учебнике мы увидели три различных способа обработки объектов JSON с помощью WebClient . Мы видели способы указания типов массивов Объект и наши собственные пользовательские классы.

Затем мы узнали, как предоставить тип информации для получения Список с помощью Параметризированный ТипРеференс .

Как всегда, код для этой статьи доступен более на GitHub .