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
Далее, мы можем извлечь тело в наш массив Объект :
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 с пользовательским массивом
Мы можем предоставить Пользователь РестТемплет , вместо Объект :
ResponseEntityresponseEntity = 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 тип токена, где информация о типе полностью доступна во время выполнения.
С дженериков, однако, тип стирания происходит, если мы пытаемся Список
Мы можем преодолеть это с помощью токена супер типа под названием ПараметризированныйТипРеференции. Мгновенный его как анонимный внутренний класс – новый ПараметризированныйTypeReference>()
– использует тот факт, что подклассы общих классов содержат информацию о типе компиляции времени, которая не подлежит стирания типа и может потребляться через отражение.
4. Резюме
В этой статье мы увидели три различных способа обработки объектов JSON с помощью RestTemplate. Мы видели, как указать типы массивов Объект и наши собственные пользовательские классы.
Затем мы узнали, как мы предоставляем информацию о типе для получения Список с помощью Параметризированный ТипРеференс .
Как всегда, код для этой статьи доступен более на GitHub .