Ответ 1
Я вижу по крайней мере два подхода, чтобы сделать это, если вы хотите избавиться от классов-оболочек. Во-первых, используйте древовидную модель Jackson (JsonNode
), а вторая - использовать функцию десериализации, называемую UNWRAP_ROOT_VALUE
.
Альтернатива 1: используйте JsonNode
При десериализации JSON с использованием Jackson существует несколько способов управления тем типом объектов, которые должны быть созданы. ObjectMapper
может десериализовать JSON, например, a Map
, JsonNode
(через метод readTree
) или POJO.
Если вы комбинируете метод readTree
с преобразованием POJO
, обертки могут быть полностью удалены. Пример:
// The author class (a bit cleaned up)
public class Author {
private final String givenName;
private final String surname;
@JsonCreator
public Author(
@JsonProperty("given-name") final String givenName,
@JsonProperty("surname") final String surname) {
this.givenName = givenName;
this.surname = surname;
}
public String getGivenName() {
return givenName;
}
public String getSurname() {
return surname;
}
}
Затем десериализация может выглядеть примерно так:
// The JSON
final String json = "{\"authors\":{\"author\":[{\"given-name\":\"AdrienneH.\",\"surname\":\"Kovacs\"},{\"given-name\":\"Philip\",\"surname\":\"Moons\"}]}}";
ObjectMapper mapper = new ObjectMapper();
// Read the response as a tree model
final JsonNode response = mapper.readTree(json).path("authors").path("author");
// Create the collection type (since it is a collection of Authors)
final CollectionType collectionType =
TypeFactory
.defaultInstance()
.constructCollectionType(List.class, Author.class);
// Convert the tree model to the collection (of Author-objects)
List<Author> authors = mapper.reader(collectionType).readValue(response);
// Now the authors-list is ready to use...
Если вы используете этот подход Tree Model, классы-оболочки могут быть полностью удалены.
Альтернатива 2: удалите одну из оберток и разверните корневое значение
Второй подход - удалить только одну из оберток. Предположим, что вы удалите класс Authors
, но сохраните Response
-wrapper. Если вы добавите a @JsonRootName
-nnotation, вы можете позже развернуть имя верхнего уровня.
@JsonRootName("authors") // This is new compared to your example
public class Response {
private final List<Author> authors;
@JsonCreator
public Response(@JsonProperty("author") final List<Author> authors) {
this.authors = authors;
}
@JsonProperty("author")
public List<Author> getAuthors() {
return authors;
}
}
Затем для вашего картографа просто используйте:
ObjectMapper mapper = new ObjectMapper();
// Unwrap the root value i.e. the "authors"
mapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true);
final Response responsePojo = mapper.readValue(json, Response.class);
Второй подход только удаляет один из классов-оболочек, но вместо этого функция синтаксического анализа довольно хороша.