Deserializar el mapa JSON usando Jackson no da el mapa correcto

Preguntas

  1. Para empezar, ¿la serialización JSON serializada a continuación tiene sentido?
  2. Si es así, ¿por qué no estoy recuperando el Mapa?
  3. ¿Qué puedo hacer al respecto en el lado de la deserialización?

JSON serialización de Map <String, String> propiedad (extracto):

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

POJO para la deserialización:

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

Causa esta excepción:

 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 

Los atributos Objeto cuando se inspecciona en el depurador después de la deserialización:

Objeto deserializado inspeccionado en depurador

Inspección adicional después de cambiar a:

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

Attributes.entrySet ()Attributes.get ("entrada")

Dependencias:

  • 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

Si vamos a convertir Map a json:

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

La salida será:

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

Como podemos ver, no hay key/value .

Solución

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

Atributos

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

Entrada

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

Lanzacohetes

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

Salida:

 operating system 
  • ¿Cómo puedo inyectar un objeto en Android Priority Job Queue con Dagger 2?
  • Problemas de serialización de RealmList (Realm / Gson / Intent)
  • Archivo de serialización en Android
  • ¿Cómo arreglar Unmarshalling código de tipo desconocido XXX en el desplazamiento YYY en Android?
  • ¿Se limpia la actividad de Android instanceState durante la actualización de la aplicación?
  • Android Realm - Objeto de Realm de paso usando Intent
  • Serialización de objetos XML de Android
  • ¿La aplicación de Android restablece el cambio de orientación, la mejor manera de manejar?
  • Intención de envío dentro de otra Intención
  • Serializar una ArrayList
  • ¿Cómo serializar un paquete?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.