How to extract ObjectMapper from JAX-RS Client?

耗尽温柔 提交于 2019-11-29 09:35:19
necromancer

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.

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:

@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:

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

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

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.

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);
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!