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

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

Spring RestTemplate может преобразовать массив JSON в различные типы Java. Мы смотрим на варианты и как подготовить тип-специфический список.

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

1. Обзор

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

Весной мы можем использовать РестТемплет для выполнения синхронных запросов HTTP. Данные обычно возвращаются как JSON, так и РестТемплет может преобразовать его для нас.

В этом учебнике мы собираемся изучить, как мы можем преобразовать JSON Array в три различные структуры объектов в Java: Массив Объект , Массив POJO и Список POJO.

2. JSON, POJO и сервис

Представим, что у нас есть конечная точка http://localhost:8080/users возвращая список пользователей в качестве следующего JSON:

[{
  "id": 1,
  "name": "user1",
}, {
  "id": 2,
  "name": "user2"
}]

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

public class User {
    private int id;
    private String name;

    // getters and setters..
}

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

public class UserConsumerServiceImpl implements UserConsumerService {

    private final RestTemplate restTemplate;

    public UserConsumerServiceImpl(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

...
}

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

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

3.1. RestTemplate с объектом Array

Во-первых, давайте позвоним с RestTemplate.getForEntity и использовать ОтветВечность типа Объект для сбора ответа:

ResponseEntity responseEntity =
   restTemplate.getForEntity(BASE_URL, Object[].class);

Далее, мы можем извлечь тело в наш массив Объект :

Object[] objects = responseEntity.getBody();

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

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

ObjectMapper mapper = new ObjectMapper();

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

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

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

С помощью этого метода, мы можем по существу читать массив что- в Объект массива в Java. Это может быть удобно, если мы только хотели подсчитать результаты, например. Тем не менее, он не поддается хорошо для дальнейшей обработки. Мы должны были приложить дополнительные усилия для преобразования его в тип, с который мы могли бы работать.

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

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

3.2. RestTemplate с пользовательским массивом

Мы можем предоставить Пользователь РестТемплет , вместо Объект :

  ResponseEntity responseEntity = 
    restTemplate.getForEntity(BASE_URL, User[].class); 
  User[] userArray = responseEntity.getBody();
  return Arrays.stream(userArray) 
    .map(User::getName) 
    .collect(Collectors.toList());

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

3.3. RestTemplate со списком пользователей и параметризированнымTypeReference

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

ResponseEntity> responseEntity = 
  restTemplate.exchange(
    BASE_URL,
    HttpMethod.GET,
    null,
    new ParameterizedTypeReference>() {}
  );
List users = responseEntity.getBody();
return users.stream()
  .map(User::getName)
  .collect(Collectors.toList());

Это производит Список которые мы хотим использовать.

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

В первых двух примерах Весна может легко deserialize JSON в Пользователь.class тип токена, где информация о типе полностью доступна во время выполнения.

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

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

4. Резюме

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

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

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