2011-06-16 27 views
25

Tengo un objeto de dominio que tiene un mapa:no puede encontrar un (Mapa) deserializer clave para el tipo [tipo simple, com.comcast.ivr.core.domain.AutoHandlingSlotKey clase]

private Map<AutoHandlingSlotKey, LinkedHashSet<AutoFunction>> autoHandling; 

Cuando serializar el objeto, me sale esto:

"autoHandling" : [ "java.util.HashMap", { 
} ], 

clave de este mapa es un objeto personalizado:

public class AutoHandlingSlotKey implements Serializable { 
    private FunctionalArea slot; // ENUM 
    private String returnView; // ENUM 

Por lo tanto, no estoy seguro de cómo corregir este problema que seguir recibiendo cuando deserializar el objeto:

org.codehaus.jackson.map.JsonMappingException: Can not find a (Map) Key deserializer for type [simple type, class com.comcast.ivr.core.domain.AutoHandlingSlotKey] 

Puede alguien ayudarme a entender cómo corregir este problema si hago NO tener acceso al objeto de dominio para modificar?

Respuesta

16

De forma predeterminada, Jackson intenta serializar Java Maps como objetos JSON (pares clave/valor), por lo que el objeto clave Map debe ser serializado de alguna manera como una cadena; y debe haber un deserializador de claves coincidente (y registrado). La configuración predeterminada solo admite un pequeño conjunto de tipos de JDK (String, numbers, enum). Así que mapper no tiene idea de cómo tomar un String y crear AutoHandlingSlotKey. (de hecho me sorprende que serializador no fracasó por la misma razón)

dos maneras obvias para resolver este son:

  • implementar y registrar un "deserializer tecla"
  • implementar y certificar una costumbre deserializador para Maps.

En su caso, es probablemente más fácil hacer ex. Es posible que también desee implementar un serializador de clave personalizado para garantizar que las claves sean serializadas en el formato adecuado.

La forma más fácil de registrar serializadores y deserializadores es por Module interface que se agregó en Jackson 1.7 (y se extendió en 1.8 para admitir serializadores/deserializadores de claves).

+0

Después de una prueba rápida, creo que las claves se serializan utilizando su método toString, que probablemente no sea lo que usted desea. Crear un serializador de claves parece una buena opción. – Suma

+0

Esa es la alternativa si no se encuentra nada más. Hay alternativas: si el tipo tiene un constructor público de cadenas simples, por ejemplo, que se usará. O un método de fábrica de argumento de cadena único anotado con '@ JsonCreator'.Esto eliminará la necesidad de escribir y registrar un deserializador de clave personalizado. – StaxMan

+0

Genial, pero usted describe el deserializador (lo intentaré). ¿Qué pasa con el serializador? En mi caso, se usó String (para una clase de caso Scala). ¿Qué otras opciones hay para el serializador, además de escribir las mías? – Suma

8

Esto se preguntó hace mucho tiempo, y es el primer resultado de google al buscar el error, pero la respuesta aceptada no tiene código y puede ser confuso para un principiante de jackson (me). Eventualmente encontré this answer que me ayudó.

Por lo tanto, como se indica en la respuesta aceptada, Implementar y registrar un "deserializador de claves" es el camino a seguir. Puedes hacer esto así.

SimpleModule simpleModule = new SimpleModule(); 
simpleModule.addKeyDeserializer(YourClass.class, new YourClassKeyDeserializer()); 
objectMapper.registerModule(simpleModule); 

y para la clase, todo lo que tiene que hacer es:

class YourClassKeyDeserializer extends KeyDeserializer 
{ 
    @Override 
    public Object deserializeKey(final String key, final DeserializationContext ctxt) throws IOException, JsonProcessingException 
    { 
     return null; // replace null with your logic 
    } 
} 

Eso es todo! No hay anotación en las clases, no deserializador personalizado para mapas, etc.

Cuestiones relacionadas