2011-06-16 14 views
25

Ho un oggetto di dominio che ha una mappa:Impossibile trovare un (Map) deserializzatore chiave per il tipo di [tipo semplice, classe com.comcast.ivr.core.domain.AutoHandlingSlotKey]

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

Quando ho serializzare l'oggetto, ottengo questo:

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

chiave di questa mappa è un oggetto personalizzato:

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

Quindi, io non sono sicuro di come risolvere il problema che ho continuo a ricevere quando ho deserializzare l'oggetto:

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

Qualcuno può aiutarmi a capire come risolvere questo problema se faccio NON avere accesso all'oggetto dominio da modificare?

risposta

16

Per impostazione predefinita, Jackson tenta di serializzare Java Maps come oggetti JSON (coppie chiave/valore), pertanto l'oggetto chiave Mappa deve essere serializzato in qualche modo come stringa; e deve esserci un deserializzatore di corrispondenza (e registrato). La configurazione predefinita supporta solo un piccolo set di tipi JDK (String, numeri, enum). Quindi il mapper non ha idea di come prendere una stringa e creare AutoHandlingSlotKey. (infatti sono sorpreso che serializzatore non ha mancato per lo stesso motivo)

Due modi ovvi per risolvere questo sono:

  • implementare e registrare un "deserializzatore tasto"
  • Implementare e registrare un personalizzato deserializzatore per Maps.

Nel tuo caso è probabilmente più facile fare ex. Si potrebbe anche voler implementare il serializzatore chiave personalizzato, per garantire che le chiavi siano serializzatore nel formato corretto.

Il modo più semplice per registrare serializzatori e deserializzatori è Module interface aggiunto in Jackson 1.7 (ed esteso in 1.8 per supportare serializzatori/deserializzatori chiave).

+0

Dopo un test rapido, penso che le chiavi siano serializzate usando il loro metodo toString, che probabilmente non è quello che vuoi. Creare un serializzatore di chiavi sembra una buona opzione. – Suma

+0

Questo è il fallback se non viene trovato nient'altro. Ci sono alternative: se il tipo ha un costruttore pubblico di argomenti con stringa singola, ad esempio, verrà utilizzato. Oppure un metodo factory con argomento a stringa singola annotato con '@ JsonCreator'.Ciò eliminerà la necessità di scrivere e registrare un deserializzatore di chiave personalizzato. – StaxMan

+0

Ottimo - ma tu descrivi il deserializzatore (lo proverò). Che ne pensi di serializzatore? Nel mio caso è stato usato toString (per una classe caso Scala). Quali altre opzioni ci sono per il serializzatore, oltre a scrivere il mio? – Suma

8

Questo è stato chiesto molto tempo fa ed è il primo risultato di Google quando si cerca l'errore, ma la risposta accettata non ha codice e potrebbe confondere un principiante di jackson (me). Alla fine ho trovato this answer che mi ha aiutato.

Quindi, come indicato nella risposta accettata, l'implementazione e la registrazione di un "key deserializer" è la strada da percorrere. Puoi farlo in questo modo.

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

E per la classe, tutto ciò che dovete fare è:

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

Questo è tutto! Nessuna annotazione sulle classi, non deserializzatore personalizzato per le mappe, ecc.

Problemi correlati