Adding JAR with ObjectMapper makes my ObjectMapper

2019-02-17 19:39发布

问题:

How can I make my object mapper work in situation when there is another object mapper defined in jar from dependencies ?

I'm trying to use Swagger with Jersey 2 which is being run under Jetty. The problem is that as soon as I add Swagger JAX-RX jar into classpath my object mapper is not discovered therefore I lose custom serialization of my objects.

Here is how my object mapper defined

@Provider
public class ObjectMapperProvider implements ContextResolver<ObjectMapper> {
}

I've posted issue to Swagger's maintainers where you could read details.

After hours of debugging in internals of Jersey I found that Swagger's own object mapper com.wordnik.swagger.jaxrs.json.JacksonJsonProvider calls super.setMapper(commonMapper) that sets non-null value to ProviderBase._mapperConfig._mapper. Later when http request handler attempts to serialize instance of my class call ends up in ProviderBase.locateMapper which has following body

public MAPPER locateMapper(Class<?> type, MediaType mediaType)
{
    // First: were we configured with a specific instance?
    MAPPER m = _mapperConfig.getConfiguredMapper();
    if (m == null) {
        // If not, maybe we can get one configured via context?
        m = _locateMapperViaProvider(type, mediaType);
        if (m == null) {
            // If not, let's get the fallback default instance
            m = _mapperConfig.getDefaultMapper();
        }
    }
    return m;
}

in correct code-flow _mapperConfig.getConfiguredMapper() returns null which subsequently causes invocation of _locateMapperViaProvider which finds my custom mapper. With Swagger it defaults to com.fasterxml.jackson.jaxrs.json.JsonMapperConfigurator and my custom json serializers never get invoked.

I created small project which reproduces this problem here.

How would you guys suggest to fix this ? I could probably specify deserializer on each property of type TTLocalDate but it'll pollute the code :(

回答1:

As noted by fehguy in the issue report, using the latest Swagger release and using the SwaggerSerializers should fix this issue. Where previously the Swagger JacksonJsonProvider would be used for all serializions, the SwaggerSerializers is only used for the Swagger model object

public class SwaggerSerializers implements MessageBodyWriter<Swagger> {

    @Override
    public boolean isWriteable(Class type, Type genericType, Annotation[] annotations,
                               MediaType mediaType) {
        return Swagger.class.isAssignableFrom(type);
    }