杰克逊处理包裹的元素

时间:2012-05-26 05:00:04

标签: java json jackson

我正在解析来自last.fm API的响应。但似乎他们使用了一些包装来做出一些反应,这会引起一些痛苦。举一个例子:

 {
   "artists":{
      "artist":[
         {
            "name":"Coldplay",
            "playcount":"816763",
            "listeners":"120815",
            "mbid":"cc197bad-dc9c-440d-a5b5-d52ba2e14234",
            "url":"http:\/\/www.last.fm\/music\/Coldplay",
            "streamable":"1"
         },
         {
            "name":"Radiohead",
            "playcount":"846668",
            "listeners":"99135",
            "mbid":"a74b1b7f-71a5-4011-9441-d0b5e4122711",
            "url":"http:\/\/www.last.fm\/music\/Radiohead",
            "streamable":"1"
         }
      ],
      "@attr":{
         "page":"1",
         "perPage":"2",
         "totalPages":"500",
         "total":"1000"
      }
   }
}

不仅响应被包装在艺术家对象中,而且对象数组也有一个对象包装器。

这是一个包装类,如:

public class LastFMArtistWrapper {
    public List<Artist> artists;

}

不行。我解决了这个问题,创建了两个包装类,但这看起来非常难看。我们有什么方法可以使用杰克逊的@XMLElementWrapper这样的东西吗?

1 个答案:

答案 0 :(得分:5)

您从提供程序返回的JSON响应是不同对象层次结构的序列化表示,但根据您的描述,听起来您实际上只需要使用并使用此表示的特定子集,即集合艺术家。

镜像此表示的一种解决方案涉及创建相同的Java类层次结构,这会以不需要的类的形式创建额外的开销。据我所知,这是你想避免的。

org.json项目创建了一个通用的JSONObject类,它表示更大的JSON表示中的单个通用键/值对。 JSONObject可以包含其他JSONObject和JSONArrays,镜像表示,而无需维护和编写额外类的额外开销。

因此,这两个对象可以在JSON表示中的多个层次结构中重用,而不需要复制结构。以下是您可以继续操作的示例:

// jsonText is the string representation of your JSON
JSONObject jsonObjectWrapper = new JSONObject(jsonText);  

// get the "artists" object
JSONObject jsonArtists = jsonObjectWrapper.get("artists");

// get the array and pass it to Jackson's ObjectMapper, using TypeReference
  // to deserialize the JSON ArrayList to a Java ArrayList.
List<Artist> artists = objectMapper.readValue(
        jsonObjectWrapper.getString("artist"),
            new TypeReference<ArrayList<Artist>>() { });

使用上面的方法,您可以减少额外的开销,即必须编写额外的POJO对象层,除了添加不必要的混乱之外什么都不做。

TestCollectionDeserialization包含一些使用集合时readValue方法的示例,可能会有所帮助。