简体   繁体   English

杰克逊不能反序列化空阵列

[英]Jackson Can not deserialize empty array

Im reading the Facebook Insights and trying to get Jackson to map the JSON to Object. 我正在阅读Facebook Insights并试图让Jackson将JSON映射到Object。 If all the data comes in without empty, i have it working. 如果所有数据都没有空,我就可以使用了。 But Im having a problem trying to deserialize empty array of key value. 但我有一个问题,试图反序列化键值的空数组。 Even after trying this post: How to prevent null values inside a Map and null fields inside a bean from getting serialized through Jackson it did not resolve the problem :( 即使在尝试这篇文章后: 如何防止Map内的空值和bean内的空字段通过Jackson序列化它没有解决问题:(

This is the JSON : 这是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"}}

My current code does not like this at all --> "value":[] 我当前的代码根本不喜欢这个 - > “value”:[]

And the follwing is my Object: 以下是我的对象:

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;
    }
}
}

My code snippet as follows: 我的代码片段如下:

    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);

The full stack trace: 完整堆栈跟踪:

com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.util.LinkedHashMap out of START_ARRAY token at [Source: java.io.StringReader@625a80df; com.fasterxml.jackson.databind.JsonMappingException:无法在[来源:java.io.StringReader@625a80df;中的START_ARRAY标记中反序列化java.util.LinkedHashMap的实例。 line: 1, column: 1603] (through reference chain: com.social.facebook.model.Insights["data"]->com.social.facebook.model.Data["values"]->com.social.facebook.model.Values["value"]) 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) at com.fasterxml.jackson.databind.deser.std.MapDeserializer.deserialize(MapDeserializer.java:306) at 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) at com.fas line:1,column:1603](通过引用链:com.social.facebook.model.Insights [“data”] - > com.social.facebook.model.Data [“values”] - > com.social.facebook .model.Values [“value”])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)at com.fasterxml.jackson.databind.deser.std.MapDeserializer.deserialize(MapDeserializer.java:306)at com.fasterxml.jackson.databind.deser位于com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:375)的com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet中的.std.MapDeserializer.deserialize(MapDeserializer.java:26) (MethodProperty.java:98)位于com.fas的com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:308) terxml.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) at 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.SettableBean terxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:121)位于com.fasterxml.jackson.databind的com.fasterxml.jackson.databind.deser.std.ObjectArrayDeserializer.deserialize(ObjectArrayDeserializer.java:147)。 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)位于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.SettableBean Property.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) at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:121) at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:2796) at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:1942) Property.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)at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:121)at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:2796)at com.fasterxml.jackson .databind.ObjectMapper.readValue(ObjectMapper.java:1942)

As explained by others, you are trying to map JSON Array into Java Map, something that is not allowed by default. 正如其他人所解释的那样,您正在尝试将JSON数组映射到Java Map中,这是默认情况下不允许的。

But it may be possible to allow empty JSON Array to map to java.util.Map . 但是可以允许空JSON数组映射到java.util.Map by enabling DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT : 通过启用DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT

objectMapper.enable(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT);

this at least works in case of a POJO type; 这至少适用于POJO类型; I do not recall if this works for other Java types that usually take JSON Object. 我不记得这是否适用于通常采用JSON Object的其他Java类型。

The value field in your model is declared as Map while the corresponding JSON property can be either an empty array or a key-value map. 模型中的value字段声明为Map而相应的JSON属性可以是空数组或键值映射。 Jackson cannot assign an empty array to a map field. 杰克逊无法将空数组分配给地图字段。

Assuming that you wish to solve the problem on the client side, you can modify the setValue method to accept a generic Object and then verify whether it is a map or an array (actually List since Jackson deserialize arrays as Java collections). 假设您希望在客户端解决问题,您可以修改setValue方法以接受通用Object ,然后验证它是映射还是数组(实际上是List因为Jackson将数组反序列化为Java集合)。 Here is an example: 这是一个例子:

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));
    }
}

Output: 输出:

Bean{value={}}
Bean{value={}}
Bean{value={a=b}}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM