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

时间:2022-06-10 19:33:12

I am using Jersey JAX-RS client (version 2.0). I know it is using a Jackson ObjectMapper to generate and parse JSON. I want to use that same object to generate JSON for some java classes so that I can write them to a log.

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

I know I can create a new instance of ObjectMapper but I prefer to request Jersey Client to give me a reference to the one it is using. How can I do this? Jersey 2.0 is aware of Jackson because it includes a JacksonFeature class that is used to configure the Jackson feature in the first place.

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

3 个解决方案

#1


18  

I solved this by adding the following static members:

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

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

Note that the second declaration is not needed just to configure FAIL_ON_UNKNOWN_PROPERTIES or FAIL_ON_EMPTY_BEANS; I use object_mapper for some other reasons.

请注意,仅配置FAIL_ON_UNKNOWN_PROPERTIES或FAIL_ON_EMPTY_BEANS不需要第二个声明;我出于其他一些原因使用object_mapper。

#2


17  

Jersey does not actually explicitly configure an ObjectMapper instance, rather it delegates to JacksonJsonProvider, which in turn uses a default mapper instance. You can trace through the JacksonProviderProxy code to see how it works. You can create and customize a shared mapper to be used throughout your application by defining a context resolver:

Jersey实际上并没有显式配置ObjectMapper实例,而是委托给JacksonJsonProvider,而JacksonJsonProvider又使用默认的映射器实例。您可以浏览JacksonProviderProxy代码以查看其工作原理。您可以通过定义上下文解析器来创建和自定义要在整个应用程序中使用的共享映射器:

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

The Jackson provider will retrieve its mapper instance from this resolver, and you could do the same in your code, as so:

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

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

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

#3


0  

Was not able to get to the jersey object mapper to configure it, based on the other solutions here (using jackson 2.8.3). (I suspect it may be related to osgi container, but nonetheless...) A brute-force way around it is to get the Response object from the Client and invoke your own instance of ObjectMapper on it. Then that same instance can be reused with your explicit configuration elsewhere as well.

基于此处的其他解决方案(使用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);

#1


18  

I solved this by adding the following static members:

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

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

Note that the second declaration is not needed just to configure FAIL_ON_UNKNOWN_PROPERTIES or FAIL_ON_EMPTY_BEANS; I use object_mapper for some other reasons.

请注意,仅配置FAIL_ON_UNKNOWN_PROPERTIES或FAIL_ON_EMPTY_BEANS不需要第二个声明;我出于其他一些原因使用object_mapper。

#2


17  

Jersey does not actually explicitly configure an ObjectMapper instance, rather it delegates to JacksonJsonProvider, which in turn uses a default mapper instance. You can trace through the JacksonProviderProxy code to see how it works. You can create and customize a shared mapper to be used throughout your application by defining a context resolver:

Jersey实际上并没有显式配置ObjectMapper实例,而是委托给JacksonJsonProvider,而JacksonJsonProvider又使用默认的映射器实例。您可以浏览JacksonProviderProxy代码以查看其工作原理。您可以通过定义上下文解析器来创建和自定义要在整个应用程序中使用的共享映射器:

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

The Jackson provider will retrieve its mapper instance from this resolver, and you could do the same in your code, as so:

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

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

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

#3


0  

Was not able to get to the jersey object mapper to configure it, based on the other solutions here (using jackson 2.8.3). (I suspect it may be related to osgi container, but nonetheless...) A brute-force way around it is to get the Response object from the Client and invoke your own instance of ObjectMapper on it. Then that same instance can be reused with your explicit configuration elsewhere as well.

基于此处的其他解决方案(使用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);