10

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

我想做的是注册一个“默认”杰克逊ObjectMapper,然后能够注册另一个功能,该功能提供了ObjectMapper一些专门的配置,在某些情况下将“覆盖”“默认” ObjectMapper

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

@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提供程序注入/解析。但是,在实践中,我看到的是提供者的“顺序”似乎是随机的(我猜不是,但我无法弄清楚如何控制顺序)。有时“覆盖”出现在“默认”之前,一切正常,但在下一次服务器启动时,顺序会发生变化。

我试图通过多种方式使其发挥作用,包括:

  • 手动注册ContextResolver<ObjectMapper>实现(以不同的顺序)
  • ContextResolver<ObjectMapper>通过@Provider注解注册实现
  • 注册时指定优先级

我正在使用以下内容:

  • 泽西 2.8
  • 杰克逊 2.3.3

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

4

2 回答 2

3

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

@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;
        }
    }
}
于 2014-05-12T21:52:30.133 回答
0

最新的方法是

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

在最新版本的杰克逊中获得 ALLOW_UNQUOTED_FIELD_NAMES。

于 2019-12-16T01:06:59.497 回答