使用 ObjectMapper 添加 JAR 使我的 ObjectMapper 不可发现

2022-01-21 00:00:00 swagger java jax-rs jersey jersey-2.0

当依赖项在 jar 中定义了另一个对象映射器时,如何使我的对象映射器工作?

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

我正在尝试将 Swagger 与 Jersey 2 在 Jetty 下运行.问题是,一旦我将 Swagger JAX-RX jar 添加到类路径中,我的对象映射器就没有被发现,因此我失去了对象的自定义序列化.

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> {
}

我已将 issue 发布给 Swagger 的维护人员,您可以在其中阅读详情.

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

在 Jersey 内部进行数小时调试后,我发现 Swagger 自己的对象映射器 com.wordnik.swagger.jaxrs.json.JacksonJsonProvider 调用 super.setMapper(commonMapper) 将非空值设置为 ProviderBase._mapperConfig._mapper.稍后,当 http 请求处理程序尝试序列化我的类调用的实例时,会以 ProviderBase.locateMapper 结束,它具有以下正文

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;
}

在正确的代码流中 _mapperConfig.getConfiguredMapper() 返回 null ,这随后会导致调用 _locateMapperViaProvider 找到我的自定义映射器.使用 Swagger,它默认为 com.fasterxml.jackson.jaxrs.json.JsonMapperConfigurator 并且我的自定义 json 序列化程序永远不会被调用.

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.

你们建议如何解决这个问题?我可能会在 TTLocalDate 类型的每个属性上指定反序列化器,但它会污染代码:(

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 :(

推荐答案

正如 fehguy 在问题报告中指出的那样,使用最新的 Swagger 版本并使用 SwaggerSerializers 应该可以解决此问题.以前 Swagger JacksonJsonProvider 将用于 all 序列化,而 SwaggerSerializers 是 只用于 Swagger 模型对象

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);
    }

相关文章