首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >使用Jackson将嵌套数组反序列化为ArrayList

使用Jackson将嵌套数组反序列化为ArrayList
EN

Stack Overflow用户
提问于 2015-01-12 12:38:31
回答 1查看 24.6K关注 0票数 23

我有一段JSON,看起来像这样:

代码语言:javascript
复制
{
  "authors": {
    "author": [
      {
        "given-name": "Adrienne H.",
        "surname": "Kovacs"
      },
      {
        "given-name": "Philip",
        "surname": "Moons"
      }
    ]
   }
 }

我创建了一个类来存储作者信息:

代码语言:javascript
复制
public class Author {
    @JsonProperty("given-name")
    public String givenName;
    public String surname;
}

和两个包装类:

代码语言:javascript
复制
public class Authors {
    public List<Author> author;
}

public class Response {
    public Authors authors;
}

这是有效的,但是有两个包装器类似乎是不必要的。我想找到一种方法来删除Authors类,并有一个列表作为入口类的属性。这样的事情在杰克逊身上是可能的吗?

更新

用定制的反序列化程序解决了这个问题:

代码语言:javascript
复制
public class AuthorArrayDeserializer extends JsonDeserializer<List<Author>> {

    private static final String AUTHOR = "author";
    private static final ObjectMapper mapper = new ObjectMapper();
    private static final CollectionType collectionType =
            TypeFactory
            .defaultInstance()
            .constructCollectionType(List.class, Author.class);

    @Override
    public List<Author> deserialize(JsonParser jsonParser, DeserializationContext deserializationContext)
            throws IOException, JsonProcessingException {

        ObjectNode objectNode = mapper.readTree(jsonParser);
        JsonNode nodeAuthors = objectNode.get(AUTHOR);

        if (null == nodeAuthors                     // if no author node could be found
                || !nodeAuthors.isArray()           // or author node is not an array
                || !nodeAuthors.elements().hasNext())   // or author node doesn't contain any authors
            return null;

        return mapper.reader(collectionType).readValue(nodeAuthors);
    }
}

并像这样使用它:

代码语言:javascript
复制
@JsonDeserialize(using = AuthorArrayDeserializer.class)
public void setAuthors(List<Author> authors) {
    this.authors = authors;
}

感谢@wassgren的想法。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-01-12 15:27:14

如果您想摆脱包装器类,我认为至少有两种方法可以做到这一点。第一种是使用Jackson Tree Model (JsonNode),第二种是使用称为UNWRAP_ROOT_VALUE的反序列化特性。

备选方案1:使用 JsonNode

在使用Jackson对JSON进行反序列化时,有多种方法可以控制要创建的对象类型。ObjectMapper可以将JSON反序列化为MapJsonNode (通过readTree-method)或POJO。

如果将readTree-method与POJO转换结合使用,则可以完全删除包装器。示例:

代码语言:javascript
复制
// 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;
    }
}

然后,反序列化可以看起来像这样:

代码语言:javascript
复制
// 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...

如果您使用这种树模型方法,则可以完全删除包装器类。

备选方案2:移除一个包装器并解开根值第二种方法是只移除一个包装器。假设您删除了Authors类,但保留了Response-wrapper。如果您添加了@JsonRootName-annotation,则可以稍后展开顶级名称。

代码语言:javascript
复制
@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;
    }
}

然后,对于您的映射器,只需使用:

代码语言:javascript
复制
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);

第二种方法只删除了一个包装类,但是解析函数相当不错。

票数 16
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27895376

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档