将Jersey中的Jackson与多个已配置的ObjectMapper一起使用

将Jersey中的Jackson与多个已配置的ObjectMapper一起使用,jersey,jackson,jax-rs,jackson-modules,Jersey,Jackson,Jax Rs,Jackson Modules,是否可以使用Jackson设置Jersey,以便使用多个已配置的对象映射器进行序列化/反序列化 我希望能够注册一个“默认”JacksonObjectMapper,然后能够注册另一个功能,该功能提供了一个带有一些特殊配置的ObjectMapper,在某些情况下将“覆盖”默认的ObjectMapper 例如,此ContextResolver将用于“默认”映射器: 我在JacksonJsonProvider代码中看到了Jackson支持的ObjectMapperprovider注入/解析。然而,在实践

是否可以使用Jackson设置Jersey,以便使用多个已配置的
对象映射器进行序列化/反序列化

我希望能够注册一个“默认”Jackson
ObjectMapper
,然后能够注册另一个功能,该功能提供了一个带有一些特殊配置的
ObjectMapper
,在某些情况下将“覆盖”默认的
ObjectMapper

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

我在
JacksonJsonProvider
代码中看到了Jackson支持的
ObjectMapper
provider注入/解析。然而,在实践中,我看到的是提供者的“顺序”似乎是随机的(我猜不是,但我无法确定如何控制顺序)。有时“覆盖”在“默认”之前,一切正常,但在下一次服务器启动时,顺序会发生变化

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

  • 手动注册
    ContextResolver
    实现(以不同的顺序)
  • 通过
    @Provider
    注释注册
    ContextResolver
    实现
  • 注册时指定优先级
我正在使用以下工具:

  • 泽西岛2.8
  • 杰克逊2.3.3
也许我采取了完全错误的方法?
有没有更好的方法来实现我的目标?
也许我应该定义两个独立的JAX-RS应用程序,并为每个应用程序配置一个ObjectMapper配置?

您可以配置提供程序的顺序,但在这种情况下,最好使用一个提供程序:

@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;
        }
    }
}
@Provider
公共类JacksonMapperProvider实现ContextResolver{
私有最终对象映射器defaultMapper;
私有最终对象映射器specializedMapper;
公共JacksonMapperProvider(){
defaultMapper=createDefaultMapper();
specializedMapper=createSpecializedMapper();
}
私有静态对象映射器createDefaultMapper(){
返回新的ObjectMapper()
.setSerializationInclusion(包括.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\u UNQUOTED\u CONTROL\u CHARS,true);
}
私有静态对象映射器createSpecializedMapper(){
返回新的ObjectMapper()
.disable(序列化功能。将日期写入时间戳)
.setDateFormat(新的SimpleDateFormat(“yyyy-MM-dd'T'HH:MM:ss.SSS”))
.registerModule(新的SpecializedModule1())
.registerModule(新的SpecializedModule 2());
}
@凌驾
公共对象映射器getContext(类类型){
if(SomeType.isAssignableFrom(type)){
返回专业化apper;
}
否则{
返回默认映射器;
}
}
}
最新的方法是

new ObjectMapper().configure(com.fasterxml.jackson.core.JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);

获取jackson最新版本中的ALLOW_UNQUOTED_FIELD_名称。

谢谢。这是我最初为使其工作所做的,然而,我希望保持应用程序的不同模块/区域的独立性和不可知性,并避免由于需要不同的映射程序而导致潜在的“大型提供者”。你能详细解释一下为什么“在这种情况下最好使用一个提供者”吗?我有一个类似的问题变得更糟,因为我们想为Jackson注释使用mixin,而不是将它们放在实际的类上。通过创建自己的
@JsonMixin
注释,然后在运行时扫描所有注释对象,我们解决了问题。您可以执行类似的操作,动态配置您的
ObjectMapper
,并只维护一个。我发现,一旦您拥有
ObjectMapper defaultMapper=return new ObjectMapper()
,它就不同于默认的
JacksonJsonProvider
实例。至少不适用于
JacksonJaxbJsonProvider
@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;
        }
    }
}
new ObjectMapper().configure(com.fasterxml.jackson.core.JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);