杰克逊处理包裹的元素

Vin*_*lho 7 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"
      }
   }
}
Run Code Online (Sandbox Code Playgroud)

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

所以包装类如下:

public class LastFMArtistWrapper {
    public List<Artist> artists;

}
Run Code Online (Sandbox Code Playgroud)

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

jmo*_*253 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>>() { });
Run Code Online (Sandbox Code Playgroud)

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

TestCollectionDeserialization在处理集合时包含一些readValue方法的示例,可能会有所帮助.