如何从JAX-RS客户端提取ObjectMapper?

时间:2013-05-04 23:56:10

标签: json jersey jackson jax-rs jersey-client

我正在使用Jersey JAX-RS客户端(版本2.0)。我知道它使用Jackson ObjectMapper来生成和解析JSON。我想使用同一个对象为某些java类生成JSON,以便我可以将它们写入日志。

我知道我可以创建一个新的ObjectMapper实例,但我更愿意请求Jersey客户端给我一个它正在使用的实例。我怎样才能做到这一点? Jersey 2.0知道Jackson,因为它包含一个JacksonFeature类,用于首先配置Jackson功能。

3 个答案:

答案 0 :(得分:19)

我通过添加以下静态成员解决了这个问题:

private static JacksonJsonProvider jackson_json_provider = new JacksonJaxbJsonProvider()
      .configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false)
      .configure(SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS, false);

private static ObjectMapper object_mapper = jackson_json_provider.locateMapper(
      Object.class, MediaType.APPLICATION_JSON_TYPE);

private static Client client = ClientBuilder.newClient().register(jackson_json_provider);

请注意,仅配置FAIL_ON_UNKNOWN_PROPERTIESFAIL_ON_EMPTY_BEANS不需要第二个声明;我出于其他原因使用object_mapper

答案 1 :(得分:17)

Jersey实际上并没有显式配置ObjectMapper实例,而是委托给JacksonJsonProvider,后者又使用默认的映射器实例。您可以追踪the JacksonProviderProxy code以查看其工作原理。您可以通过定义context resolver

来创建和自定义要在整个应用程序中使用的共享映射器
@Provider
public class ObjectMapperContextResolver implements
        ContextResolver<ObjectMapper> {
    private ObjectMapper mapper = null;

    public ObjectMapperContextResolver() {
        super();

        // Illustrate configuration of the mapper instance
        mapper = new ObjectMapper().configure(
                SerializationConfig.Feature.WRAP_ROOT_VALUE, true).configure(
                DeserializationConfig.Feature.UNWRAP_ROOT_VALUE, true);
    }

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

Jackson提供程序将从此解析程序中检索其映射器实例,您可以在代码中执行相同操作,如下所示:

public class MyResource {
    @Context
    private ContextResolver<ObjectMapper> mapperResolver;

    public void someResourceMethod() {
        final ObjectMapper mapper = mapperResolver.getContext(Object.class);
    }
}

答案 2 :(得分:0)

根据此处的其他解决方案(使用jackson 2.8.3)无法到达球衣对象映射器进行配置。 (我怀疑它可能与osgi容器有关,但仍然......)围绕它的一种强力方法是从客户端获取Response对象并在其上调用自己的ObjectMapper实例。然后,同样的实例也可以在其他地方使用显式配置重复使用。

Client client = ClientBuilder.newClient();
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
...
Response r = client.target(URL).request().get();
MyDtoClass dto = mapper.readValue((InputStream)(r.getEntity()), MyDtoClass.class);