Using Jackson ObjectMapper with Jersey Using Jackson ObjectMapper with Jersey spring spring

Using Jackson ObjectMapper with Jersey


EDIT: Don't use the old approach below as it produces bugs (at least with with android device, see EDIT2 for more details). As of my tests, Jersey v2.6 seems to fix the problem with the @Provide, which approach did not work. I was able to get it work with this simple provider:

@Providerpublic class JerseyMapperProvider implements ContextResolver<ObjectMapper> {    private static ObjectMapper apiMapper = ObjectMapperManager.createMapperForApi();    @Override    public ObjectMapper getContext(Class<?> type)    {        return apiMapper;    }}

So please don't use my hack from below.


OLD APPROACH

Using

@Providerpublic class MyObjectMapperProvider implements ContextResolver<ObjectMapper>

was not working for me (Jersey 2.4 & Jackson 2.3) and maybe this is due to a in the jackson provider reported bug in the code where the ContextResolver should be registered in JacksonJsonProvider.java (2.3rc1):

 @Overrideprotected ObjectMapper _locateMapperViaProvider(Class<?> type, MediaType mediaType){    if (_providers != null) {        ContextResolver<ObjectMapper> resolver = _providers.getContextResolver(ObjectMapper.class, mediaType);        /* Above should work as is, but due to this bug         *   [https://jersey.dev.java.net/issues/show_bug.cgi?id=288]         * in Jersey, it doesn't. But this works until resolution of         * the issue:         */        if (resolver == null) {            resolver = _providers.getContextResolver(ObjectMapper.class, null);        }        if (resolver != null) {            return resolver.getContext(type);        }    }    return null;}

But at least I cannot access https://jersey.dev.java.net/issues/show_bug.cgi?id=288, so I don't know what this bug is about.

But I found a workaround (a hack if you so will). Just extend JacksonJsonProvider with the proper annotation and return your ObjectMapper like this:

@Provider@Consumes(MediaType.APPLICATION_JSON) // NOTE: required to support "non-standard" JSON variants@Produces(MediaType.APPLICATION_JSON)public class JacksonHackProvider extends JacksonJsonProvider {    @Override    protected ObjectMapper _locateMapperViaProvider(Class<?> type, MediaType mediaType) {        return new MyCustomObjectMapper();    }}

No need to do anything it will register itself (check with log, it will register the first time you access a json rest service). This is now working for me, not elegant, but I gave up.

EDIT: Use with caution - Im experiencing a bug maybe related to this hack: Android volley cannot send a POST/PUT request with a request body, always getting 400 from the framework, I will investigate and report my findings.

EDIT2: This hack was indeed responsible for a generic 400 whenever an Android app with volley and OKHTTP client tried tried to do a POST or PUT request so don't use this - in my test jersey 2.6 seems to fix this so you can use @Provide approach


Unfortunately everyone makes this much harder than it needs to be. The Jersey team in their wisdom decided to integrate Jackson 1.9, so their stuff wont' help you.

But it was pretty easy for me. Just do this:

    <dependency>        <groupId>com.fasterxml.jackson.core</groupId>        <artifactId>jackson-databind</artifactId>        <version>2.3.0</version>    </dependency>    <dependency>        <groupId>com.fasterxml.jackson.jaxrs</groupId>        <artifactId>jackson-jaxrs-json-provider</artifactId>        <version>2.3.0</version>    </dependency>

Now GET RID OF THIS:

<dependency>    <groupId>org.glassfish.jersey.media</groupId>    <artifactId>jersey-media-json-jackson</artifactId>    <version>2.4.1</version></dependency>

Then in your web.xml change this line:

<param-value>ie.cit.nimbus.sample</param-value>

To be:

<param-value>ie.cit.nimbus.sample,com.fasterxml.jackson.jaxrs.json</param-value>

That should do it.


Using Jersey 2.13, you can force the @Provider to use the same ObjectMapper should only create one ObjectMapper:

package com.example.api.environment.configs;import com.fasterxml.jackson.databind.ObjectMapper;import com.fasterxml.jackson.databind.SerializationFeature;import com.fasterxml.jackson.datatype.joda.JodaModule;import javax.ws.rs.ext.ContextResolver;import javax.ws.rs.ext.Provider;@Providerpublic class JacksonConfig implements ContextResolver<ObjectMapper> {  private final ObjectMapper objectMapper;  public JacksonConfig() {    objectMapper = new ObjectMapper()          .configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false)          .registerModule(new JodaModule());  };  @Override  public ObjectMapper getContext(Class<?> type) {    return objectMapper;  }}

I use this to @Autowire in my ObjectMapper to generate json-schema documents on the fly.