【问题标题】:Deserializing JSON map with "key" & "value" properties does not work with Jackson使用“key”和“value”属性反序列化 JSON 映射不适用于 Jackson
【发布时间】:2014-01-09 03:58:46
【问题描述】:

问题

  1. 首先,下面的序列化 JSON 序列化有意义吗?
  2. 如果是这样,为什么我没有取回地图?
  3. 在反序列化方面我能做些什么?

Map 属性的 JSON 序列化(摘录):

{
  "attributes": {
    "entry": [
      {
        "key": "operating system",
        "value": "GNU/Linux"
      },
      {
        "key": "allergies",
        "value": "weed"
      }
    ]
  }
}

用于反序列化的 POJO:

class Contact implements Comparable<Contact>, Serializable {
    @JsonProperty("attributes")
    private Map<String, String> attributes;
    ...
}

导致此异常:

Thread-4889 An exception occurred during request network execution :Could not read JSON: Can not deserialize instance of java.lang.String out of START_ARRAY token
            at [Source: libcore.net.http.FixedLengthInputStream@43822760; line: 1, column: 17] (through reference chain: com.example.model.Contact["attributes"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.lang.String out of START_ARRAY token
            at [Source: libcore.net.http.FixedLengthInputStream@43822760; line: 1, column: 17] (through reference chain: com.example.model.Contact["attributes"])
    org.springframework.http.converter.HttpMessageNotReadableException: Could not read JSON: Can not deserialize instance of java.lang.String out of START_ARRAY token
            at [Source: libcore.net.http.FixedLengthInputStream@43822760; line: 1, column: 17] (through reference chain: com.example.model.Contact["attributes"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.lang.String out of START_ARRAY token
            at [Source: libcore.net.http.FixedLengthInputStream@43822760; line: 1, column: 17] (through reference chain: com.example.model.Contact["attributes"])
            at org.springframework.http.converter.json.MappingJackson2HttpMessageConverter.readInternal(MappingJackson2HttpMessageConverter.java:126)
            at org.springframework.http.converter.AbstractHttpMessageConverter.read(AbstractHttpMessageConverter.java:147)
            at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:76)
            at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:484)
            at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:439)
            at org.springframework.web.client.RestTemplate.getForObject(RestTemplate.java:237)
            at com.example.providers.Query$1.loadDataFromNetwork(Query.java:99)
            at com.octo.android.robospice.request.CachedSpiceRequest.loadDataFromNetwork(CachedSpiceRequest.java:45)
            at com.octo.android.robospice.request.RequestRunner.processRequest(RequestRunner.java:130)
            at com.octo.android.robospice.request.RequestRunner$1.run(RequestRunner.java:197)
            at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:390)
            at java.util.concurrent.FutureTask.run(FutureTask.java:234)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
            at java.lang.Thread.run(Thread.java:841)
     Caused by: com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.lang.String out of START_ARRAY token
            at [Source: libcore.net.http.FixedLengthInputStream@43822760; line: 1, column: 17] (through reference chain: com.example.model.Contact["attributes"])
            at com.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:691)
            at com.fasterxml.jackson.databind.deser.std.StringDeserializer.deserialize(StringDeserializer.java:46)
            at com.fasterxml.jackson.databind.deser.std.StringDeserializer.deserialize(StringDeserializer.java:11)
            at com.fasterxml.jackson.databind.deser.std.MapDeserializer._readAndBindStringMap(MapDeserializer.java:430)
            at com.fasterxml.jackson.databind.deser.std.MapDeserializer.deserialize(MapDeserializer.java:312)
            at com.fasterxml.jackson.databind.deser.std.MapDeserializer.deserialize(MapDeserializer.java:26)
            at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:525)
            at com.fasterxml.jackson.databind.deser.impl.FieldProperty.deserializeAndSet(FieldProperty.java:106)
            at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:242)
            at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:118)
            at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:227)
            at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.des

反序列化后在调试器中检查时的属性对象:

改成后进一步检查:

@JsonProperty("attributes")
private Map<String, List<Map<String, String>>> attributes;

依赖关系:

  • com.fasterxml.jackson.core:jackson-core:2.3.0
  • com.fasterxml.jackson.core:jackson-databind:2.3.0
  • com.fasterxml.jackson.core:jackson-annotations:2.3.0

【问题讨论】:

    标签: java android json serialization jackson


    【解决方案1】:

    如果我们将Map 转换为json:

        Map<String, String> map = new HashMap<String, String>();
        map.put("operating system", "GNU/Linux");
        map.put("allergies", "weed");
    

    输出将是:

    {"operating system":"GNU/Linux","allergies":"weed"}
    

    我们可以看到没有key/value。

    解决方案

    WrapperObject

    @JsonIgnoreProperties(ignoreUnknown = true)
    public class WrapperObject { // we can give any name to class, its only external {}    
    
        private Attributes attributes;
    
        public WrapperObject() {}
    
        public Attributes getAttributes() {
            return attributes;
        }    
    }
    

    属性

    @JsonIgnoreProperties(ignoreUnknown = true)  
    public class Attributes {
    
        public Attributes() {}
    
        private ArrayList<Entry> entry;  
    
        public ArrayList<Entry> getEntry() {
            return entry;
        }    
    }
    

    参赛作品

    @JsonIgnoreProperties(ignoreUnknown = true)    
    public  class Entry {
    
        private String key;
        private String value;
           
        
        public Entry() {}
    
    
        public String getKey() {
            return key;
        }
    
    
        public String getValue() {
            return value;
        }
    }
    

    启动器

    public static void main(String[] args) throws JsonParseException, JsonMappingException,     IOException {
        String str = "{" + 
                "  \"attributes\": {" + 
                "    \"entry\": [" + 
                "      {" + 
                "        \"key\": \"operating system\"," + 
                "        \"value\": \"GNU/Linux\"" + 
                "      }," + 
                "      {" + 
                "        \"key\": \"allergies\"," + 
                "        \"value\": \"weed\"" + 
                "      }" + 
                "    ]" + 
                "  }" + 
                "}";
    
        
        
        ObjectMapper mapper = new ObjectMapper();
        WrapperObject mj = mapper.readValue(str, WrapperObject.class);
    
        if(mj == null){
            System.err.println("null");
        }
        // dummy check
        System.out.println(mj.getAttributes().getEntry().get(0).getKey());
    }
    

    输出:

    operating system
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-01-01
      • 2019-01-20
      • 2018-02-28
      • 2013-04-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-12
      相关资源
      最近更新 更多