Использование Jackson в качестве клиентского сериализатора Джерси
Вопрос
Можно ли использовать Jackson в качестве сериализатора / маршаллера для данных JSON вместо JAXB при использовании Jersey Client API?
Если да, то как это настроить?
Решение
Хорошо, я выяснил это, в конце концов, это оказывается довольно просто:
ClientConfig cc = new DefaultClientConfig();
cc.getClasses().add(JacksonJsonProvider.class);
Client clientWithJacksonSerializer = Client.create(cc);
JacksonJsonProvider поставляется из пакета jackson-jaxrs.
Другие советы
Вы можете пропустить создание внешней конфигурации и зарегистрировать поставщика напрямую:
Client client = ClientBuilder.newClient().register(JacksonJsonProvider.class)
Решение с JacksonJaxbJsonProvider
Распространенным способом использования Jackson с пользовательской конфигурацией в Jersey client было использование JacksonJaxbJsonProvider
например, вот так
JacksonJaxbJsonProvider provider = new JacksonJaxbJsonProvider();
provider.setMapper(yourObjectMapper());
Client client = ClientBuilder.newClient(new ClientConfig(provider));
К сожалению , в Джерси 2.26 они скопировали JacksonJaxbJsonProvider
класс
из com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider
артефакт (Джексон)
чтобы org.glassfish.jersey.media:jersey-media-json-jackson
артефакт (Джерси)
и измененная упаковка
из com.fasterxml.jackson.jaxrs.json
Для org.glassfish.jersey.jackson.internal.jackson.jaxrs.json
.
Этот подход все еще можно использовать, его просто нужно изменить JacksonJaxbJsonProvider
импорт.
Помимо JacksonJaxbJsonProvider
находясь сейчас в internal
недостатком пакета также является
то, что вы должны знать, на какой версии Jersey выполняется ваш код, что может быть проблемой, когда для разных зависимостей требуются разные версии Jersey.
Лучшее решение с ContextResolver<ObjectMapper>
Лучшая возможность как настроить Jackson в Джерси клиент заключается в том, чтобы использовать тот же способ, как он настроен в Джерси сервер который заключается в создании ObjectMapper
провайдер , подобный этому:
@Provider
@Produces(MediaType.APPLICATION_JSON)
public class ObjectMapperProvider implements ContextResolver<ObjectMapper> {
private ObjectMapper objectMapper = yourObjectMapper();
@Override
public ObjectMapper getContext(Class<?> objectType) {
return objectMapper;
}
}
и используйте его, например, вот так:
ClientConfig clientConfig = new ClientConfig();
clientConfig.register(JacksonFeature.class); // usually auto-discovered
clientConfig.register(new ObjectMapperProvider());
Client client = ClientBuilder.newClient(clientConfig);
Если у вас есть и сервер, и клиент, вы можете повторно использовать ObjectMapperProvider
класс.
Похоже, что этот подход работает с версии Jersey 2.9.
Возможно, вы также захотите попробовать org.codehaus.jackson.jaxrs.JacksonJaxbJsonProvider (jackson-jaxrs 1.6.1)
.
Я столкнулся с аналогичной проблемой, но для меня ни одно из приведенных здесь предложений не сработало.То, что сработало для меня, было приведено ниже фрагментом кода:
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Client;
...
ClientBuilder clientBuilder = ClientBuilder.newBuilder()
clientBuilder.register(JacksonFeature.class);
...
Client client = clientBuilder.build();
Ключевым изменением стало использование JacksonFeature.class
- это происходит от jersey-media-json-jackson-x.yy.jar
Я получил подсказку, как использовать это решение, из этой статьи - http://www.baeldung.com/jersey-jax-rs-client
Для джерси 2.22.2 и Джексон 2.7.2 зависимости gradle - это:
dependencies {
compile("com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:2.7.2")
compile("org.glassfish.jersey.core:jersey-client:2.22.2")
}
Пример клиентского кода - это:
final String name = "world";
final Client client = ClientBuilder.newClient().register(JacksonJaxbJsonProvider.class);
final WebTarget target = client.target("http://localhost:8080").path("hello").path(name);
final Message message = target.request().get(Message.class);
System.out.println(message.getWelcomeMessage()); // hello world