Пример кода ниже.
Используя Spring Boot 2.2, я хочу связаться с REST API. API, который я пытаюсь использовать, оборачивает объекты в родительской модели для разбивки на страницы и сортировки и помещает массив фактических объектов в поле results
. Как бы я смоделировал свой Java-код, чтобы Джексон «знал», как десериализовать ответы API в мои java-объекты?
Я пытался решить эту проблему с использованием универсального в ApiResponse и передатьожидаемый тип поля при выполнении запроса get:
String URL_GET_DOGS = "https://localhost/api/v1/dogs/"
ApiResponse<Dog> response = this.restTemplate.getForObject(URL_GET_DOGS, response.getClass());
Это компилирует и выполняет ...
Ожидаемый результат: Успешно создан объект ApiResponse с полем результатов, состоящим из спискаDogs.
Фактический результат: Успешно создан объект ApiResponse, но поле результатов представляет собой список объектов.
Таким образом, Джексон не будет приводить список результатов должным образом и вместо этогоПохоже, я получаю List<Object>
вместо List<Dog>
для моего results
поля в моем объекте ApiResponse. Таким образом, я получаю свойства неправильного типа или свойства, которые вообще не хочу десериализовать! См. Пример автомобиля.
Теперь я вернулся к решению на основе интерфейса, но Я застрял. Джексон (по праву, потому что нет способа вывести правильный класс ... ) жалуется, что не знает, как десериализовать абстрактные типы, и мне нужно предоставить конкретную реализацию, я не могу использовать аннотации Джексона класса, как описано здесь , потому что я не контролирую API, генерирующийответы.
Единственный выход из этого, который я вижу сейчас, - это использование классов для каждого типа ответа, но это означает много дублирующегося кода для полей подкачки и сортировки. Что я делаю не так?
Пример JSON:
{
"count": 84,
"next": "http://localhost:80/api/v1/dogs/?limit=2&offset=2",
"previous": null,
"results": [
{
"name": "Pebbles"
},
{
"name": "Spot"
}
]
}
и другая конечная точка:
{
"count": 22,
"next": "http://localhost:80/api/v1/cars/?limit=2&offset=2",
"previous": null,
"results": [
{
"brand": "Mercedes",
"horse_power": 120,
"field_i_dont": "want_to_deserialize"
},
{
"brand": "BMW",
"horse_power": 180,
"field_i_dont": "want_to_deserialize"
}
]
}
Пример кода:
public class ApiResponse<T>{
// paging and sorting
private Long count;
private String next;
private String previous;
// the actual objects
private List<T> results;
// No-args constructor, getters & setters
}
public class Dog {
private String name;
// No-args constructor, getters & setters
}
@JsonIgnoreProperties(ignoreUnknown = true)
public class Car {
private int horsePower;
private String brand;
// No-args constructor, getters & setters
}