在Jersey中使用Jackson,配置多个ObjectMappers [英] Using Jackson in Jersey with multiple configured ObjectMappers

查看:820
本文介绍了在Jersey中使用Jackson,配置多个ObjectMappers的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用多个已配置的 ObjectMappers ,是否可以使用Jackson设置Jersey进行序列化/反序列化?

Is it possible to setup Jersey using Jackson for serialization/deserialization using multiple configured ObjectMappers?

我是什么我希望能够做的是注册一个默认Jackson ObjectMapper ,然后能够注册另一个提供 ObjectMapper 有一些特殊配置,在某些情况下会覆盖默认 ObjectMapper

What I would like to be able to do is register a "default" Jackson ObjectMapper and then have the ability to register another feature which provides an ObjectMapper with some specialized configuration which under certain circumstance will "override" the "default" ObjectMapper.

例如,此 ContextResolver 将用于默认映射器:

For example, this ContextResolver would be for the "default" mapper:

@Provider
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public class JacksonMapperProvider implements ContextResolver<ObjectMapper> {
    private final ObjectMapper mObjectMapper;

    public JacksonMapperProvider() {
        mObjectMapper = createMapper();
    }

    protected abstract ObjectMapper createMapper() {
        ObjectMapper mapper = createMapper();

        return mapper
            .setSerializationInclusion(Include.ALWAYS)
            .configure(JsonParser.Feature.ALLOW_COMMENTS, true)
            .configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true)
            .configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true)
            .configure(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true);
    }

    @Override
    public ObjectMapper getContext(Class<?> type) {
        return mObjectMapper;
    }
}

ContextResolver 将覆盖默认映射器:

@Provider
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public class SpecializedMapperProvider implements ContextResolver<ObjectMapper> {
    private final ObjectMapper mObjectMapper;

    public SpecializedMapperProvider() {
        mObjectMapper = createMapper();
    }

    protected abstract ObjectMapper createMapper() {
        ObjectMapper mapper = createMapper();

        return mapper
            .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
            .setDateFormat(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS"))
            .registerModule(new SpecializedModule1())
            .registerModule(new SpecializedModule2());
    }

    @Override
    public ObjectMapper getContext(Class<?> type) {
        if(SomeType.isAssignableFrom(type)) {
            return mObjectMapper;
        }
        return null;
    }
}

我在 JacksonJsonProvider中看到 Jackson支持的代码 ObjectMapper 提供者注入/解析。然而,在实践中,我所看到的是提供者的顺序似乎是随机的(我猜它不是,但我不能理清如何控制顺序)。有时覆盖出现在默认之前,一切正常,但在下一次服务器启动时,订单会发生变化。

I see in the JacksonJsonProvider code that Jackson supports ObjectMapper provider injection/resolution. However, in practice, what I am seeing is that the "order" of the providers seems random (I'm guessing it's not, but I can't sort out how to control the order). Sometimes the "override" comes before the "default" and everything works, but on the next server startup the order changes.

我试图通过多种方式实现这一目标,包括:

I have attempted to get this to work in a number of ways including:


  • 手动注册 ContextResolver< ObjectMapper> 实现(按不同的顺序)

  • 注册 ContextResolver< ObjectMapper> ; 实施 @Provider 注释

  • 注册时指定优先级

  • Registering the ContextResolver<ObjectMapper> implementations manually (in differing orders)
  • Registering the ContextResolver<ObjectMapper> implementations via @Provider annotations
  • Specifying a priority when registering

我使用以下内容:


  • Jersey 2.8

  • Jackson 2.3.3

也许我采取了一种完全不正确的方法?

Is有更好的方法来实现我想要做的事情吗?
也许我应该只定义两个独立的JAX-RS应用程序并为每个应用程序配置一个ObjectMapper?

Perhaps I am taking a completely incorrect approach?
Is there a better way to achieve what I am trying to do? Maybe I should just define two separate JAX-RS applications and have a single ObjectMapper configuration for each?

推荐答案

你可以配置提供商的顺序,但实际上最好在这种情况下使用一个提供商:

You can configure the order of providers, but it would actually be best to use one provider in this situation:

@Provider
public class JacksonMapperProvider implements ContextResolver<ObjectMapper> {
    private final ObjectMapper defaultMapper;
    private final ObjectMapper specializedMapper;

    public JacksonMapperProvider() {
        defaultMapper = createDefaultMapper();
        specializedMapper = createSpecializedMapper();
    }

    private static ObjectMapper createDefaultMapper() {
        return new ObjectMapper()
            .setSerializationInclusion(Include.ALWAYS)
            .configure(JsonParser.Feature.ALLOW_COMMENTS, true)
            .configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true)
            .configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true)
            .configure(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true);
    }

    private static ObjectMapper createSpecializedMapper() {
        return new ObjectMapper()
            .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
            .setDateFormat(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS"))
            .registerModule(new SpecializedModule1())
            .registerModule(new SpecializedModule2());
    }

    @Override
    public ObjectMapper getContext(Class<?> type) {
        if (SomeType.isAssignableFrom(type)) {
            return specializedMapper;
        }
        else {
            return defaultMapper;
        }
    }
}

这篇关于在Jersey中使用Jackson,配置多个ObjectMappers的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆