2011-06-16 12 views
25

Mam obiektu domeny, która ma mapy:nie mogę znaleźć (mapa) Key Deserializator dla rodzaju [typu prostego, klasa com.comcast.ivr.core.domain.AutoHandlingSlotKey]

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

kiedy serializacji obiektu, otrzymuję to:

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

klucz ta mapa jest zwyczaj obiektu:

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

Tak, nie jestem pewien, jak rozwiązać ten problem, ja Wciąż dostaję kiedy deserializowania obiektu:

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

Czy ktoś może mi pomóc zrozumieć, w jaki sposób rozwiązać ten problem, jeśli robię NIE mieć dostęp do obiektu domeny zmodyfikować?

Odpowiedz

16

Domyślnie Jackson próbuje serializować mapy Java jako obiekty JSON (pary klucz/wartość), więc obiekt klucza mapy musi być w jakiś sposób serializowany jako ciąg; i musi być dopasowany (i zarejestrowany) kluczowy deserializator. Domyślna konfiguracja obsługuje tylko mały zestaw typów JDK (String, numbers, enum). Zatem program mapujący nie ma pojęcia, jak pobrać ciąg i utworzyć z niego AutoHandlingSlotKey. (w rzeczywistości jestem zaskoczony, że serializer nie omieszkał dla samego powodu)

dwa oczywiste sposoby, aby rozwiązać ten problem to:

  • Wdrożenie i zarejestrować „klucz Deserializator”
  • Wdrożenie i zarejestrować zwyczaj deserializer dla Map.

W twoim przypadku prawdopodobnie łatwiej jest zrobić dawniej. Możesz również zaimplementować serializator z kluczem niestandardowym, aby zapewnić, że klucze są serializowane w odpowiednim formacie.

Najprostszym sposobem zarejestrowania serializerów i deserializatorów jest Module interface, który został dodany w Jackson 1.7 (i rozszerzony w wersji 1.8 w celu obsługi kluczowych serializatorów/deserializatorów).

+0

Po szybkim teście, wydaje mi się, że klucze są serializowane za pomocą ich metody toString, co prawdopodobnie często nie jest tym, czego potrzebujesz. Tworzenie serializera kluczowego wydaje się być dobrą opcją. – Suma

+0

To jest awaryjne, jeśli nic innego nie zostanie znalezione. Istnieją alternatywy: jeśli typ ma publiczny konstruktor z pojedynczym ciągiem, na przykład, który będzie użyty. Lub metoda fabularna z pojedynczym ciągiem, opisana za pomocą '@ JsonCreator'.Spowoduje to usunięcie potrzeby zapisu i zarejestrowania deserializatora klucza niestandardowego. – StaxMan

+0

Świetnie - ale opisujesz deserializer (spróbuję tego). A co z serializerem? W moim przypadku użyto toString (dla klasy przypadku Scala). Jakie są inne opcje serializera, oprócz pisania własnego? – Suma

8

To pytanie zostało zadane dawno temu i jest pierwszym wynikiem w Google podczas wyszukiwania błędu, ale zaakceptowana odpowiedź nie zawiera kodu i może być myląca dla początkującego użytkownika (mnie) w języku jackson. W końcu znalazłem this answer, które pomogło.

Tak, jak stwierdzono w przyjętej odpowiedzi, wdrożenie i zarejestrowanie "kluczowego deserializatora" jest drogą do zrobienia. Możesz to zrobić w ten sposób.

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

I klasy, wszystko co musisz zrobić, to:

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

To jest to! Brak adnotacji na klasach, a nie niestandardowy deserializator dla map itp.