Deserializing non-string map keys with Jackson

前端 未结 3 1612
说谎
说谎 2020-12-01 14:35

I have a a map that looks like this:

public class VerbResult {
    @JsonProperty(\"similarVerbs\")
    private Map> similarVerbs         


        
相关标签:
3条回答
  • 2020-12-01 14:53

    Building on the answer given here that suggests to implement a Module with a deserializer. The JodaTime Module is an easy to understand full example of a module containing serializers and deserializers.

    Please note that the Module feature was introduced in Jackson version 1.7 so you might need to upgrade.

    So step by step:

    1. create a module containing a (de)serializer for your class based on the Joda example
    2. register that module with mapper.registerModule(module);

    and you'll be all set

    0 讨论(0)
  • 2020-12-01 14:56

    As mentioned above the trick is that you need a key deserializer (this caught me out as well). In my case a non-String map key was configured on my class but it wasn't in the JSON I was parsing so an extremely simple solution worked for me (simply returning null in the key deserializer).

    public class ExampleClassKeyDeserializer extends KeyDeserializer
    {
        @Override
        public Object deserializeKey( final String key,
                                      final DeserializationContext ctxt )
           throws IOException, JsonProcessingException
        {
            return null;
        }
    }
    
    public class ExampleJacksonModule extends SimpleModule
    {
        public ExampleJacksonModule()
        {
            addKeyDeserializer(
                ExampleClass.class,
                new ExampleClassKeyDeserializer() );
        }
    }
    
    final ObjectMapper mapper = new ObjectMapper();
    mapper.registerModule( new ExampleJacksonModule() );
    
    0 讨论(0)
  • 2020-12-01 15:07

    After a day of searching, I came across a simpler way of doing it based on this question. The solution was to add the @JsonDeserialize(keyUsing = YourCustomDeserializer.class) annotation to the map. Then implement your custom deserializer by extending KeyDeserializer and override the deserializeKey method. The method will be called with the string key and you can use the string to build the real object, or even fetch an existing one from the database.

    So first in the map declaration:

    @JsonDeserialize(keyUsing = MyCustomDeserializer.class)
    private Map<Verb, List<Verb>> similarVerbs;
    

    Then create the deserializer that will be called with the string key.

    public class MyCustomDeserializer extends KeyDeserializer {
        @Override
        public MyMapKey deserializeKey(String key, DeserializationContext ctxt) throws IOException, JsonProcessingException {
            //Use the string key here to return a real map key object
            return mapKey;
        }
    }
    

    Works with Jersey and Jackson 2.x

    0 讨论(0)
提交回复
热议问题