Как извлечь ObjectMapper из JAX-RS Client?

Я использую клиент Джерси JAX-RS (версия 2.0). Я знаю, что использует Jackson ObjectMapper для генерации и анализа JSON. Я хочу использовать тот же самый объект для создания JSON для некоторых классов Java, чтобы я мог записать их в журнал.

Я знаю, что могу создать новый экземпляр ObjectMapper, но я предпочитаю просить Джерси-Клиента дать мне ссылку на тот, который он использует. Как я могу это сделать? Джерси 2.0 знает Джексона, потому что он включает класс JacksonFeature, который используется для настройки функции Джексона в первую очередь.

Ответы

Ответ 1

Я решил это, добавив следующие статические элементы:

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_PROPERTIES или FAIL_ON_EMPTY_BEANS; Я использую object_mapper по другим причинам.

Ответ 2

На самом деле Джерси не явно настраивает экземпляр ObjectMapper, а делегирует его 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;
    }
}

Поставщик Jackson будет извлекать свой экземпляр сопоставления из этого распознавателя, и вы можете сделать то же самое в своем коде, что и так:

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

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

Ответ 3

Не удалось добраться до устройства отображения джерси, чтобы настроить его, основываясь на других решениях здесь (используя 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);