Search code examples
spring-bootjacksonjackson2jackson-databind

Jackson deserializer priority?


I have a Spring Boot app that is modeling ActityStreams objects and for the most part Jackson's Polymorphic Deserialization works well.

There are 'objects' in the JSON which are references (links) and not JSON objects with type information. For instance "actor":"https://some.actors.href/ rather than

"actor":{
   "type":"Actor",
   "name":"SomeActor"
 }

I've written custom deserializers and and placed them on the fields to deal with this

@JsonDeserialize (using = ActorOrLinkDeserializer.class)
private Actor actor;

However my ActorOrLinkDeserializer is instantiated but never called and Jackson complains with Missing type id when trying to resolve subtype of [simple type, class org.w3.activity.streams.Actor]: missing type id property 'type' (for POJO property 'actor') which is from the polymorphic deserializer.

It appears that the polymorphic deserialization code takes precedence over my local @JsonDeserialize annotation and I need a way to force my code to run first.

I've tried using my own ObjectMapper rather than Boot's and there's no difference.

I'd appreciate pointers and suggestions.


Solution

  • It turns-out there's a fairly simple solution to this problem using a DeserializationProblemHandler.

    What I've implemented that works for all test cases so far is

    1.

    objectMapper.addHandler(new DeserProblemHandler());
    

    or register with Spring Boot.

    2.

    public class DeserProblemHandler extends DeserializationProblemHandler {
       public JavaType handleMissingTypeId(DeserializationContext ctxt, JavaType baseType, TypeIdResolver idResolver, String failureMsg) {
          return TypeFactory.defaultInstance().constructType(baseType.getRawClass());
       }
    }
    
    1. Add a constructor to each of the polymorphic classes that takes a string argument which is the href.