7

我正在解析来自 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;

}

不会工作。我解决了这个问题,创建了两个包装类,但这看起来真的很难看。有什么方法可以在 Jackson 中使用 @XMLElementWrapper 之类的东西吗?

4

1 回答 1

5

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

镜像这种表示的一种解决方案涉及创建相同的 Java 类层次结构,这会以不需要的类的形式产生额外的开销。据我了解,这是您希望避免的。

org.json 项目创建了一个通用JSONObject类,它以更大的 JSON 表示形式表示单个通用键/值对。JSONObject 可以包含其他 JSONObjects 和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 方法的一些示例,可能会有所帮助。

于 2012-05-26T05:56:58.697 回答