我正在阅读Facebook Insights并试图让杰克逊将JSON映射到Object。如果所有数据都没有空,我就可以使用了。但我有一个问题,试图反序列化键值的空数组。即使在尝试这篇文章之后:How to prevent null values inside a Map and null fields inside a bean from getting serialized through Jackson它也无法解决问题:(
这是JSON:
{"data":[{"id":"492640667465465\/insights\/page_fans_country\/lifetime","name":"page_fans_country","period":"lifetime","values":[{"value":{"MY":26315,"ID":311,"SG":77,"NP":63,"MM":56,"PH":51,"GB":44,"US":44,"KR":36,"TH":36,"IN":34,"BD":24,"PK":22,"BN":22,"AU":15,"TW":14,"VN":12,"KH":11,"YE":11,"CA":10,"JP":10,"EG":8,"ZA":7,"SA":6,"ES":6,"HK":6,"FR":6,"IT":5,"IL":5,"IR":5,"NG":5,"LK":5,"BR":5,"IQ":4,"AF":4,"AE":4,"GT":4,"RO":4,"LR":4,"RU":4,"PS":4,"DE":4,"CN":4,"LY":3,"JO":3},"end_time":"2014-08-02T07:00:00+0000"},{"value":{"MY":26326,"ID":315,"SG":77,"NP":63,"MM":56,"PH":54,"GB":44,"US":43,"TH":38,"KR":36,"IN":33,"BD":23,"BN":22,"PK":21,"AU":16,"TW":14,"VN":12,"KH":11,"YE":11,"CA":10,"JP":10,"EG":8,"ZA":7,"SA":7,"ES":6,"HK":6,"FR":6,"IT":5,"IL":5,"IR":5,"NG":5,"LK":5,"BR":5,"IQ":4,"RU":4,"CN":4,"GT":4,"RO":4,"LR":4,"AF":4,"PS":4,"DE":4,"AE":4,"LY":3,"CH":3},"end_time":"2014-08-03T07:00:00+0000"},{"value":{"MY":26338,"ID":312,"SG":79,"NP":63,"MM":55,"PH":52,"US":45,"GB":44,"TH":39,"KR":34,"IN":32,"BD":24,"BN":22,"PK":21,"AU":16,"TW":14,"KH":12,"VN":12,"CA":11,"YE":11,"JP":10,"EG":8,"ZA":7,"SA":7,"ES":6,"HK":6,"FR":6,"IT":5,"CN":5,"IR":5,"NG":5,"LK":5,"BR":5,"IL":5,"IQ":4,"AF":4,"AE":4,"GT":4,"RO":4,"LR":4,"RU":4,"PS":4,"DE":4,"NZ":3,"TR":3},"end_time":"2014-08-04T07:00:00+0000"}],"title":"Lifetime Likes by Country","description":"Lifetime: Aggregated Facebook location data, sorted by country, about the people who like your Page. (Unique Users)"},{"id":"492640667465465\/insights\/page_storytellers_by_country\/day","name":"page_storytellers_by_country","period":"day","values":[{"value":[],"end_time":"2014-08-02T07:00:00+0000"},{"value":[],"end_time":"2014-08-03T07:00:00+0000"},{"value":[],"end_time":"2014-08-04T07:00:00+0000"}],"title":"Daily Country: People Talking About This","description":"Daily: The number of People Talking About the Page by user country (Unique Users)"},{"id":"492640667465465\/insights\/page_storytellers_by_country\/week","name":"page_storytellers_by_country","period":"week","values":[{"value":{"MY":136,"IN":3,"ID":2,"BD":1,"US":1,"TN":1,"AU":1},"end_time":"2014-08-02T07:00:00+0000"},{"value":{"MY":131,"IN":3,"US":1,"TN":1,"AU":1,"ID":1},"end_time":"2014-08-03T07:00:00+0000"},{"value":{"MY":118,"IN":2,"KH":1,"TR":1,"US":1,"TN":1,"AR":1,"AU":1},"end_time":"2014-08-04T07:00:00+0000"}],"title":"Weekly Country: People Talking About This","description":"Weekly: The number of People Talking About the Page by user country (Unique Users)"},{"id":"492640667465465\/insights\/page_storytellers_by_country\/days_28","name":"page_storytellers_by_country","period":"days_28","values":[{"value":{"MY":492,"IN":5,"ID":3,"AU":2,"SG":2,"ZA":2,"US":2,"GB":2,"RO":1,"PH":1,"NP":1,"BD":1,"JO":1,"PS":1,"TN":1,"IR":1,"CA":1,"CN":1,"KR":1},"end_time":"2014-08-02T07:00:00+0000"},{"value":{"MY":499,"IN":5,"ID":3,"GB":2,"SG":2,"ZA":2,"US":2,"RO":1,"PH":1,"NP":1,"BD":1,"AU":1,"CN":1,"KR":1,"TN":1,"IR":1,"CA":1,"JO":1},"end_time":"2014-08-03T07:00:00+0000"},{"value":{"MY":501,"IN":4,"ID":3,"SG":2,"ZA":2,"US":2,"GB":2,"AU":1,"RO":1,"PH":1,"NP":1,"JO":1,"AR":1,"KR":1,"BD":1,"TR":1,"IR":1,"CA":1,"CN":1,"KH":1,"TN":1},"end_time":"2014-08-04T07:00:00+0000"}],"title":"28 Days Country: People Talking About This","description":"28 Days: The number of People Talking About the Page by user country (Unique Users)"}],"paging":{"previous":"https:\/\/graph.facebook.com\/v2.0\/492640667465465\/insights?since=1406649169&until=1406908369","next":"https:\/\/graph.facebook.com\/v2.0\/492640667465465\/insights?since=1407167569&until=1407426769"}}
我目前的代码根本不喜欢这个 - >的 “值”:[]
以下是我的对象:
import java.util.Date;
import java.util.List;
import java.util.Map;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
public class Insights {
private Data[] data;
private Paging paging;
public Data[] getData() {
return data;
}
public void setData(Data[] data) {
this.data = data;
}
public Paging getPaging() {
return paging;
}
public void setPaging(Paging paging) {
this.paging = paging;
}
/**
* inner class for Data
* @author pohsoon.yap
*
*/
public static class Data {
private String id;
private String name;
private String period;
private Values[] values;
private String title;
private String description;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPeriod() {
return period;
}
public void setPeriod(String period) {
this.period = period;
}
public Values[] getValues() {
return values;
}
public void setValues(Values[] values) {
this.values = values;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
/**
* inner class for Values
* @author pohsoon.yap
*
*/
public static class Values {
// if "value":[] then this will break
private Map<String, Integer> Value;
private String end_time;
public Map<String, Integer> getValue() {
return Value;
}
public void setValue(Map<String, Integer> value) {
Value = value;
}
public String getEnd_time() {
return end_time;
}
public void setEnd_time(String end_time) {
this.end_time = end_time;
}
}
}
public static class Paging {
private String previous;
private String next;
public String getPrevious() {
return previous;
}
public void setPrevious(String previous) {
this.previous = previous;
}
public String getNext() {
return next;
}
public void setNext(String next) {
this.next = next;
}
}
}
我的代码段如下:
ObjectMapper mapper = new ObjectMapper();
mapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
List<Insights> insightList = new ArrayList();
String insightStr = "";
try {
for (Operation operation : mq.getOperationList()){
String apiEndPoint = this.facebookGraphApiUrl + operation.getApi();
apiEndPoint = apiEndPoint.replace("{pageid}", mq.getFacebookPage().getPageId());
uri = new URI(apiEndPoint);
insightStr = facebook.getApi().restOperations().getForObject(uri, String.class);
Insights insights = mapper.readValue(insightStr, Insights.class);
完整堆栈跟踪:
com.fasterxml.jackson.databind.JsonMappingException:无法从START_ARRAY令牌中反序列化java.util.LinkedHashMap的实例 在[来源:java.io.StringReader@625a80df; line:1,column:1603](通过引用链:com.social.facebook.model.Insights [“data”] - &gt; com.social.facebook.model.Data [“values”] - &gt; com.social .facebook.model.Values [ “值”]) at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:164) at com.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:599) at com.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:593) 在com.fasterxml.jackson.databind.deser.std.MapDeserializer.deserialize(MapDeserializer.java:306) 在com.fasterxml.jackson.databind.deser.std.MapDeserializer.deserialize(MapDeserializer.java:26) at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:375) at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:98) at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:308) 在com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:121) at com.fasterxml.jackson.databind.deser.std.ObjectArrayDeserializer.deserialize(ObjectArrayDeserializer.java:147) at com.fasterxml.jackson.databind.deser.std.ObjectArrayDeserializer.deserialize(ObjectArrayDeserializer.java:18) at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:375) at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:98) at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:308) 在com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:121) at com.fasterxml.jackson.databind.deser.std.ObjectArrayDeserializer.deserialize(ObjectArrayDeserializer.java:147) at com.fasterxml.jackson.databind.deser.std.ObjectArrayDeserializer.deserialize(ObjectArrayDeserializer.java:18) at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:375) at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:98) at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:308) 在com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:121) at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:2796) 在com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:1942)
答案 0 :(得分:7)
正如其他人所解释的那样,您正在尝试将JSON数组映射到Java Map中,这是默认情况下不允许的。
但是可以允许空JSON数组映射到java.util.Map
。启用DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT
:
objectMapper.enable(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT);
这至少适用于POJO类型;我不记得这是否适用于通常采用JSON Object的其他Java类型。
答案 1 :(得分:4)
模型中的value
字段声明为Map
,而相应的JSON属性可以是空数组或键值映射。杰克逊不能将空数组分配给地图字段。
假设您希望在客户端解决问题,可以修改setValue
方法以接受通用Object
,然后验证它是映射还是数组(实际上是{{ 1}}因为Jackson将数组反序列化为Java集合。这是一个例子:
List
输出:
public class JacksonArrayAsMap {
public static class Bean {
private Map<String, Object> value;
public void setValue(Object value) {
if (value instanceof Map) {
this.value = (Map<String, Object>) value;
} else if (value instanceof List && ((List) value).size() == 0){
this.value = Collections.EMPTY_MAP;
} else {
throw new IllegalArgumentException("Invalid value: " + value);
}
}
@Override
public String toString() {
return "Bean{" +
"value=" + value +
'}';
}
}
public static void main(String[] args) throws IOException {
final String json1 = "{\"value\":{}}";
final String json2 = "{\"value\":[]}";
final String json3 = "{\"value\":{\"a\":\"b\"}}";
ObjectMapper mapper = new ObjectMapper();
System.out.println(mapper.readValue(json1, Bean.class));
System.out.println(mapper.readValue(json2, Bean.class));
System.out.println(mapper.readValue(json3, Bean.class));
}
}