如何从对象的列表类型的属性中提取 json 的数组
How to extract array of json inside an attribute of type List from an object
我正在使用 Flickr API 获取图像信息和 returns 以下 JSON:
{"photos":{"page":1,"pages":60,"perpage":100,"total":"5964","photo":[{"id":"21577339501","owner":"85277110@N02","secret":"31e850dfeb","server":"5785","farm":6,"title":"P1390956","ispublic":1,"isfriend":0,"isfamily":0}, {"id":"21577287101","owner":"85277110@N02","secret":"412990658f","server":"611","farm":1,"title":"P1400012","ispublic":1,"isfriend":0,"isfamily":0}]
我在 Spring 控制器中使用此代码反序列化 JSON:
Collection<Photos> readValues = objectMapper.readValue(new URL(url), new TypeReference<Collection<Photos>>() { });
而returns出现如下错误:
com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.util.ArrayList out of START_OBJECT token
我该如何解决这个问题?我没有找到解决方案。
Photos.class:
public class Photos {
@JsonProperty("page")
private Integer page;
@JsonProperty("pages")
private Integer pages;
@JsonProperty("perpage")
private Integer perpage;
@JsonProperty("total")
private Integer total;
@JsonProperty("photo")
@JsonDeserialize(contentAs = Photo.class, as = ArrayList.class)
private List<Photo> photo;
public Photos() {}
public Photos(Integer page, Integer pages, Integer perpage, Integer total,
List<Photo> photo) {
super();
this.page = page;
this.pages = pages;
this.perpage = perpage;
this.total = total;
this.photo = photo;
}
public Photos(List<Photo> photo) {
super();
this.photo = photo;
}
public Integer getPage() {
return page;
}
public void setPage(Integer page) {
this.page = page;
}
public Integer getPages() {
return pages;
}
public void setPages(Integer pages) {
this.pages = pages;
}
public Integer getPerpage() {
return perpage;
}
public void setPerpage(Integer perpage) {
this.perpage = perpage;
}
public Integer getTotal() {
return total;
}
public void setTotal(Integer total) {
this.total = total;
}
public List<Photo> getPhoto() {
return photo;
}
public void setPhoto(List<Photo> photo) {
this.photo = photo;
}
}
Photo.class:
public class Photo {
@JsonProperty("id")
private Integer id;
@JsonProperty("owner")
private String owner;
@JsonProperty("secret")
private String secret;
@JsonProperty("server")
private Integer server;
@JsonProperty("farm")
private Integer farm;
@JsonProperty("title")
private String title;
@JsonProperty("ispublic")
private Boolean isPublic;
@JsonProperty("isfriend")
private Boolean isFriend;
@JsonProperty("isfamily")
private Boolean isFamily;
public Photo() { }
public Photo(Integer id, String owner, String secret, Integer server,
Integer farm, String title, Boolean isPublic, Boolean isFriend,
Boolean isFamily) {
super();
this.id = id;
this.owner = owner;
this.secret = secret;
this.server = server;
this.farm = farm;
this.title = title;
this.isPublic = isPublic;
this.isFriend = isFriend;
this.isFamily = isFamily;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getOwner() {
return owner;
}
public void setOwner(String owner) {
this.owner = owner;
}
public String getSecret() {
return secret;
}
public void setSecret(String secret) {
this.secret = secret;
}
public Integer getServer() {
return server;
}
public void setServer(Integer server) {
this.server = server;
}
public Integer getFarm() {
return farm;
}
public void setFarm(Integer farm) {
this.farm = farm;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public Boolean getIsPublic() {
return isPublic;
}
public void setIsPublic(Boolean isPublic) {
this.isPublic = isPublic;
}
public Boolean getIsFriend() {
return isFriend;
}
public void setIsFriend(Boolean isFriend) {
this.isFriend = isFriend;
}
public Boolean getIsFamily() {
return isFamily;
}
public void setIsFamily(Boolean isFamily) {
this.isFamily = isFamily;
}
}
基本问题是你的 json 是 不是 一个 Collection<Photos>
,而是一个 Map<String, Photos>
,它只有一个条目 "photos" -> Photos instance
.
通过进行以下更改,我让您的 json 成功反序列化...
A) 更改正在读取的类型:
Map<String, Photos> readValues = objectMapper.readValue(json, new TypeReference<Map<String, Photos>>() { });
请注意,我是直接从字符串(而不是 URL)读取的。
B) 将 Photo.id
的类型从 Integer
更改为 Long
,因为您的 json 的 id 值远远超过最大 int 大小。
C) 我添加了您的示例 json 中缺失的两个右大括号以使其有效。
仅供参考,反序列化在 Photos
的 List<Photo> photo
字段上使用或不使用 @JsonDeserialize
注释都有效。
这里有一些可以运行的代码:
String json = "{\"photos\":{\"page\":1,\"pages\":60,\"perpage\":100,\"total\":\"5964\",\"photo\":[{\"id\":\"21577339501\",\"owner\":\"85277110@N02\",\"secret\":\"31e850dfeb\",\"server\":\"5785\",\"farm\":6,\"title\":\"P1390956\",\"ispublic\":1,\"isfriend\":0,\"isfamily\":0}, {\"id\":\"21577287101\",\"owner\":\"85277110@N02\",\"secret\":\"412990658f\",\"server\":\"611\",\"farm\":1,\"title\":\"P1400012\",\"ispublic\":1,\"isfriend\":0,\"isfamily\":0}]}}";
Map<String, Photos> readValues = new ObjectMapper().readValue(json, new TypeReference<Map<String, Photos>>() { });
我正在使用 Flickr API 获取图像信息和 returns 以下 JSON:
{"photos":{"page":1,"pages":60,"perpage":100,"total":"5964","photo":[{"id":"21577339501","owner":"85277110@N02","secret":"31e850dfeb","server":"5785","farm":6,"title":"P1390956","ispublic":1,"isfriend":0,"isfamily":0}, {"id":"21577287101","owner":"85277110@N02","secret":"412990658f","server":"611","farm":1,"title":"P1400012","ispublic":1,"isfriend":0,"isfamily":0}]
我在 Spring 控制器中使用此代码反序列化 JSON:
Collection<Photos> readValues = objectMapper.readValue(new URL(url), new TypeReference<Collection<Photos>>() { });
而returns出现如下错误:
com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.util.ArrayList out of START_OBJECT token
我该如何解决这个问题?我没有找到解决方案。
Photos.class:
public class Photos {
@JsonProperty("page")
private Integer page;
@JsonProperty("pages")
private Integer pages;
@JsonProperty("perpage")
private Integer perpage;
@JsonProperty("total")
private Integer total;
@JsonProperty("photo")
@JsonDeserialize(contentAs = Photo.class, as = ArrayList.class)
private List<Photo> photo;
public Photos() {}
public Photos(Integer page, Integer pages, Integer perpage, Integer total,
List<Photo> photo) {
super();
this.page = page;
this.pages = pages;
this.perpage = perpage;
this.total = total;
this.photo = photo;
}
public Photos(List<Photo> photo) {
super();
this.photo = photo;
}
public Integer getPage() {
return page;
}
public void setPage(Integer page) {
this.page = page;
}
public Integer getPages() {
return pages;
}
public void setPages(Integer pages) {
this.pages = pages;
}
public Integer getPerpage() {
return perpage;
}
public void setPerpage(Integer perpage) {
this.perpage = perpage;
}
public Integer getTotal() {
return total;
}
public void setTotal(Integer total) {
this.total = total;
}
public List<Photo> getPhoto() {
return photo;
}
public void setPhoto(List<Photo> photo) {
this.photo = photo;
}
}
Photo.class:
public class Photo {
@JsonProperty("id")
private Integer id;
@JsonProperty("owner")
private String owner;
@JsonProperty("secret")
private String secret;
@JsonProperty("server")
private Integer server;
@JsonProperty("farm")
private Integer farm;
@JsonProperty("title")
private String title;
@JsonProperty("ispublic")
private Boolean isPublic;
@JsonProperty("isfriend")
private Boolean isFriend;
@JsonProperty("isfamily")
private Boolean isFamily;
public Photo() { }
public Photo(Integer id, String owner, String secret, Integer server,
Integer farm, String title, Boolean isPublic, Boolean isFriend,
Boolean isFamily) {
super();
this.id = id;
this.owner = owner;
this.secret = secret;
this.server = server;
this.farm = farm;
this.title = title;
this.isPublic = isPublic;
this.isFriend = isFriend;
this.isFamily = isFamily;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getOwner() {
return owner;
}
public void setOwner(String owner) {
this.owner = owner;
}
public String getSecret() {
return secret;
}
public void setSecret(String secret) {
this.secret = secret;
}
public Integer getServer() {
return server;
}
public void setServer(Integer server) {
this.server = server;
}
public Integer getFarm() {
return farm;
}
public void setFarm(Integer farm) {
this.farm = farm;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public Boolean getIsPublic() {
return isPublic;
}
public void setIsPublic(Boolean isPublic) {
this.isPublic = isPublic;
}
public Boolean getIsFriend() {
return isFriend;
}
public void setIsFriend(Boolean isFriend) {
this.isFriend = isFriend;
}
public Boolean getIsFamily() {
return isFamily;
}
public void setIsFamily(Boolean isFamily) {
this.isFamily = isFamily;
}
}
基本问题是你的 json 是 不是 一个 Collection<Photos>
,而是一个 Map<String, Photos>
,它只有一个条目 "photos" -> Photos instance
.
通过进行以下更改,我让您的 json 成功反序列化...
A) 更改正在读取的类型:
Map<String, Photos> readValues = objectMapper.readValue(json, new TypeReference<Map<String, Photos>>() { });
请注意,我是直接从字符串(而不是 URL)读取的。
B) 将 Photo.id
的类型从 Integer
更改为 Long
,因为您的 json 的 id 值远远超过最大 int 大小。
C) 我添加了您的示例 json 中缺失的两个右大括号以使其有效。
仅供参考,反序列化在 Photos
的 List<Photo> photo
字段上使用或不使用 @JsonDeserialize
注释都有效。
这里有一些可以运行的代码:
String json = "{\"photos\":{\"page\":1,\"pages\":60,\"perpage\":100,\"total\":\"5964\",\"photo\":[{\"id\":\"21577339501\",\"owner\":\"85277110@N02\",\"secret\":\"31e850dfeb\",\"server\":\"5785\",\"farm\":6,\"title\":\"P1390956\",\"ispublic\":1,\"isfriend\":0,\"isfamily\":0}, {\"id\":\"21577287101\",\"owner\":\"85277110@N02\",\"secret\":\"412990658f\",\"server\":\"611\",\"farm\":1,\"title\":\"P1400012\",\"ispublic\":1,\"isfriend\":0,\"isfamily\":0}]}}";
Map<String, Photos> readValues = new ObjectMapper().readValue(json, new TypeReference<Map<String, Photos>>() { });