Deserialization error while using @JsonIdentityReference with resolver
See original GitHub issueI have a complex entity (ex: ComplexEntity) which has many relations and setters for its properties. Now, to create an instance of this complex entity, I have ComplexEntityController that looks like this:
@RequestMapping("/test")
public void test(ComplexDto dto) {
complexService.createEntityFromDto(dto);
}
Now assume the following DTO:
public class ComplexDto {
@JsonIdentityReference(alwaysAsId = true)
@JsonIdentityInfo(
generator = ObjectIdGenerators.PropertyGenerator.class,
property = "id",
resolver = EntityResolver.class,
scope = FooEntity.class
)
private FooEntity fooEntity;
public void setFooEntity(FooEntity fooEntity) { this.fooEntity = fooEntity; }
public FooEntity getFooEntity() { return this.fooEntity; }
}
And the EntityResolver is responsible for loading entities from database.
When I make request to the controller with the following JSON body:
{
"fooEntity": 3
}
it fails with error:
com.fasterxml.jackson.databind.JsonMappingException: Can not find a (Map) Key deserializer for type [simple type, class ir.amir.NiceEntity]
since ComplexEntity has a map inside it.
This happens, while I just expect jackson to use resolver to load my entity from database and it has nothing to do with the entity since it’s unmeaningful to fill the object while there is a resolver and the passed parameter is just a unique identifier not the whole properties.
Jackson databind version: 2.8.8 with Spring Boot
Thanks
Issue Analytics
- State:
- Created 6 years ago
- Comments:8 (4 by maintainers)
Top GitHub Comments
First of all, thank you for adding the stack trace. It certainly shows that reference chain is quite deep, going through a few POJO types. 😃
I have a feeling that your thinking of how things work is quite different from how Jackson works. Of course it does not deserialize things that are not there. But that is not the point: what it absolute MUST do is traverse type hierarchy to see what handlers are needed. These handlers are looked up once and cached; this makes a big difference in performance over trying to construct deserializers on the fly – you can see the difference by creating new
ObjectMapper
for each call, and observing 10x - 100x slowdown.Sometimes it is possible to defer some resolution; other times not. In this case it is not, at least currently.
If there was a simple stand-alone reproduction, I (or someone else with time) could see if it would be possible to improve this particular case, and defer lookup.
As to
@JsonIgnoreProperties
: that was just a suggestion for working around the need. Alternatively you could register bogus key deserializer for given type; that would work as well. Or, if there are wide varieties of types, registerKeyDeserializers
viaModule
to similarly construct not-used placeholders. These are suggestions to let your system work; you are free to use them or not.@AbiriAmir I am facing exactly the same problem now… did you manage to overcome this problem? It fails for me on null pointer exception since the abstract class has no attributes just children do.
Just simply dont understand why Jackson is not invoking deserializer for that abstract entity…