How do I get a reference to the Jackson Object Mapper in a jersey2 / hk2 application
First there is no default ObjectMapper
used by the Jackson provider. It doesn't use an ObjectMapper
at all actually. It makes use of other Jackson APIs to handle the (de)serialization.
If you want to use/inject a single ObjectMapper
instance, then you should just create a Factory
for it
public class ObjectMapperFactory implements Factory<ObjectMapper> { final ObjectMapper mapper = new ObjectMapper(); @Override public ObjectMapper provide() { return mapper; } @Override public void dispose(ObjectMapper t) {} }
Then bind it
register(new AbstractBinder(){ @Override public void configure() { bindFactory(ObjectMapperFactory.class) .to(ObjectMapper.class).in(Singleton.class); }});
One thing should be noted is that any configuration of the ObjectMapper
is not thread safe. So say you tried to configure it from your resource method, those operations are not thread safe.
Another thing to note with the Jackson provider, is that if we provide a ContextResolver
, like mentioned by @Laurentiu L, then the Jackson provider will switch to using our ObjectMapper
. In which case, if you want to use that same ObjectMapper
, then you can look it up in the Factory
. For example
public class ObjectMapperFactory implements Factory<ObjectMapper> { private final Providers providers; final ObjectMapper mapper = new ObjectMapper(); public ObjectMapperFactory(@Context Providers providers) { this.providers = providers; } @Override public ObjectMapper provide() { ContextResolver<ObjectMapper> resolver = providers.getContextResolver( ObjectMapper.class, MediaType.APPLICATION_JSON); if (resolver == null) { return mapper; } return resolver.getContext(null); } @Override public void dispose(ObjectMapper t) {} }
For the above to work (use a single ObjectMapper
), you need to make sure to implement the ContextResolver<ObjectMapper>
, and make sure to annotation the ContextResolver
with the corresponding @Produces
and @Consumes
media types.
Aside from the JacksonFeature you need to register a ContextResolver for ObjectMapper.
Simple example from the Documentation at 9.1.4.2. Configure and register
@Providerpublic class MyObjectMapperProvider implements ContextResolver<ObjectMapper> { final ObjectMapper defaultObjectMapper; public MyObjectMapperProvider() { defaultObjectMapper = createDefaultMapper(); } @Override public ObjectMapper getContext(Class<?> type) { return defaultObjectMapper; } private static ObjectMapper createDefaultMapper() { final ObjectMapper result = new ObjectMapper(); result.configure(Feature.INDENT_OUTPUT, true); return result; } // ...}
Complete code example available on Github
You will also need to register it
.register(MyObjectMapperProvider.class)