Cannot find a deserializer for non-concrete Map type [map type; class com.google.common.collect.ImmutableMap

Viewed 5942

i am using java for back-end, request sent from UI is in JSON format as shown below.

{"name":"Music"}

Below is the java code.

@PostMapping(consumes = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE},produces = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE})
    public Category insertCategory(@RequestBody Category category) {
        // TODO Auto-generated method stub
        System.out.println("entity:" +category.getName());
        CategoryServiceImpl impl = new CategoryServiceImpl();
        Category res = impl.insertCategory(category);
        return res;
    }

The response returned to UI should be json so I have used produces with MediaType.APPLICATION_JSON_VALUE as you can see above.

Also request body binds the json data to Category model object , but this is where I am getting the deserialize error (Error log shown below completely).

Category Model is shown below.

public class Category extends Entity {
    private ImmutableMap<String,Category> childCategories;

    public ImmutableMap<String, Category> getChildCategories() {
        return childCategories;
    }
    public void setCategories(Map<String,Category> categories) {
        ImmutableMap.Builder<String, Category> builder = new ImmutableMap.Builder<String, Category>();
        builder.putAll(categories);
        childCategories = builder.build();
    }
}

Entity:

public class Entity {
    private String id;
    private String name;
    private String description;
    private String title;
    private String icon;
}
//getters and setters method

Since the request sent is in json format, I am getting deserialize error and its because of map used in the model. it works if I comment the map part in the category model.

I want to use map instead of list. But how to resolve this deserialize error by keeping map itself in the model

Error log shown below.

org.springframework.web.HttpLogging : 
    Failed to evaluate Jackson deserialization for type [[simple type, class com.hiya.model.Category]]

com.fasterxml.jackson.databind.JsonMappingException:
    Cannot find a deserializer for non-concrete Map type [map type; class com.google.common.collect.ImmutableMap,
    [simple type, class java.lang.String] -> [simple type, class com.hiya.model.Category]]
    at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:306) ~[jackson-databind-2.9.7.jar:2.9.7]
    at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:268) ~[jackson-databind-2.9.7.jar:2.9.7]
    at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCacheValueDeserializer(DeserializerCache.java:244) ~[jackson-databind-2.9.7.jar:2.9.7]
    at com.fasterxml.jackson.databind.deser.DeserializerCache.findValueDeserializer(DeserializerCache.java:142) ~[jackson-databind-2.9.7.jar:2.9.7]
    at com.fasterxml.jackson.databind.DeserializationContext.findNonContextualValueDeserializer(DeserializationContext.java:467) ~[jackson-databind-2.9.7.jar:2.9.7]
    at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.resolve(BeanDeserializerBase.java:473) ~[jackson-databind-2.9.7.jar:2.9.7]
    at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:293) ~[jackson-databind-2.9.7.jar:2.9.7]
    at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCacheValueDeserializer(DeserializerCache.java:244) ~[jackson-databind-2.9.7.jar:2.9.7]
    at com.fasterxml.jackson.databind.deser.DeserializerCache.hasValueDeserializerFor(DeserializerCache.java:191) ~[jackson-databind-2.9.7.jar:2.9.7]
    at com.fasterxml.jackson.databind.DeserializationContext.hasValueDeserializerFor(DeserializationContext.java:422) ~[jackson-databind-2.9.7.jar:2.9.7]
    at com.fasterxml.jackson.databind.ObjectMapper.canDeserialize(ObjectMapper.java:2875) ~[jackson-databind-2.9.7.jar:2.9.7]

Am I going wrong somewhere ?

1 Answers

Just ran into the same issue. (looks you are using newer Jackson than me but still should work)

What you need is

<dependency>
  <groupId>com.fasterxml.jackson.datatype</groupId>
  <artifactId>jackson-datatype-guava</artifactId>
  <version>your version</version>
</dependency>

But adding the dependency is not enough. You also need to register the com.fasterxml.jackson.datatype.guava.GuavaModule.GuavaModule class into the ObjectMapper.

I suspect from your example code you are using some framework. I can not help with that one.

But if I build up the ObjectMapper and everything programatically it looks like this:

ObjectMapper mapperWithGuavaSupport = new ObjectMapper().registerModule(new GuavaModule())
MyObjectContainsImmutableMap obj = mapperWithGuavaSupport.readValue("theJsonString", MyObjectContainsImmutableMap.class);

Hope this at least give you a hint towards a direction... Good luck!

Related