使用“key”和“value”属性反序列化 JSON 映射不适用于 Jackson
Posted
技术标签:
【中文标题】使用“key”和“value”属性反序列化 JSON 映射不适用于 Jackson【英文标题】:Deserializing JSON map with "key" & "value" properties does not work with Jackson 【发布时间】:2014-01-09 03:58:46 【问题描述】:问题
-
首先,下面的序列化 JSON 序列化有意义吗?
如果是这样,为什么我没有取回地图?
在反序列化方面我能做些什么?
Map
"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【问题讨论】:
【参考方案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
【讨论】:
以上是关于使用“key”和“value”属性反序列化 JSON 映射不适用于 Jackson的主要内容,如果未能解决你的问题,请参考以下文章