我正在解析来自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这样的东西吗?
答案 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方法的示例,可能会有所帮助。