I'm running into a scenario where I need to define a one-off @FeignClient for a third party API. In this client I'd like to use a custom Jackson ObjectMapper that differs from my @Primary one. I know it is possible to override spring's feign configuration defaults however it is not clear to me how to simply override the ObjectMapper just by this specific client.
-
Have you tried it and it doesn't work? Spring Cloud Feign uses the same `HttpMessageConverters` object that Spring MVC uses. Configuring it the normal Spring Boot way should 'just work' (thought I haven't tried it myself). http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#howto-customize-the-jackson-objectmapper – spencergibb Mar 07 '16 at 21:07
-
@spencergibb I can override the ObjectMapper and it is correctly used by all Spring MVC controllers and all the Feign clients. However, what I need is a particular feign client, out of the many, to use a different object mapper from the one configured by default. I'm not sure how to even get started to make this work. – Newbie Mar 07 '16 at 22:00
-
You'd have to create a `SpringDecoder` bean using the doc link a previously posted and mess with it there. – spencergibb Mar 07 '16 at 22:04
-
@spencergibb, I got to work as shown in the answer below. Thanks for you help. – Newbie Mar 09 '16 at 05:23
-
https://blog.birost.com/a?ID=00600-16a0c674-d3f2-41a7-8e41-335e75f48dd0 – firstpostcommenter Aug 22 '22 at 08:20
5 Answers
Per the documentation, you can provide a custom decoder for your Feign client as shown below.
Feign Client Interface:
@FeignClient(value = "foo", configuration = FooClientConfig.class)
public interface FooClient{
//Your mappings
}
Feign Client Custom Configuration:
@Configuration
public class FooClientConfig {
@Bean
public Decoder feignDecoder() {
HttpMessageConverter jacksonConverter = new MappingJackson2HttpMessageConverter(customObjectMapper());
HttpMessageConverters httpMessageConverters = new HttpMessageConverters(jacksonConverter);
ObjectFactory<HttpMessageConverters> objectFactory = () -> httpMessageConverters;
return new ResponseEntityDecoder(new SpringDecoder(objectFactory));
}
public ObjectMapper customObjectMapper(){
ObjectMapper objectMapper = new ObjectMapper();
//Customize as much as you want
return objectMapper;
}
}

- 7,031
- 9
- 60
- 85
-
10worked for me simply with `return new JacksonDecoder(customObjectMapper());` – leveluptor Oct 19 '17 at 16:45
-
-
follow @NewBie`s answer, i can give the better one...
@Bean
public Decoder feignDecoder() {
return new JacksonDecoder();
}
if you want use jackson message converter in feign client, please use JacksonDecoder, because SpringDecoder will increase average latency of feignclient call in production.
<!-- feign-jackson decoder -->
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-jackson</artifactId>
<version>10.1.0</version>
</dependency>

- 1,865
- 1
- 25
- 32
-
1What's the dependency? And version? Can you show the pom.xml entry for this? – rios0rios0 Apr 08 '21 at 01:18
-
Can you quantify the increase in latency in either percentage or ms or something? I'd like a reference point for how much difference this makes. Looks clean though. – James Wynn Jul 07 '21 at 16:44
-
great improved in my impression, 10ms average improved for 8k qps in production. – suiwenfeng Jul 08 '21 at 03:29
-
@NewBie's answer has serious performance problems. During the new HttpMessageConverters
process, loadclass will be performed, resulting in a large number of thread block. If you have used this code, please modify it as follows:
ObjectFactory<HttpMessageConverters> objectFactory = () -> new HttpMessageConverters(jacksonConverter);
change to
HttpMessageConverters httpMessageConverters = new HttpMessageConverters(jacksonConverter);
ObjectFactory<HttpMessageConverters> objectFactory = () -> httpMessageConverters;
You can use JMeter and Arthas to reproduce this phenomenon, and the modified program has been greatly improved.

- 41
- 2
Define a custom decoder as below, annotated with @Configuration
and set as parameter for the feign client interface, configuration = CustomFeignClientConfig.class
@Configuration
public class CustomFeignClientConfig {
@Bean
public Decoder feignDecoder() {
return (response, type) -> {
String bodyStr = Util.toString(response.body().asReader(Util.UTF_8));
JavaType javaType = TypeFactory.defaultInstance().constructType(type);
return new ObjectMapper().readValue( bodyStr, javaType);
};
}
}

- 84
- 8
you can use SpringDecoder and SpringEncoder.
public SpringDecoder(ObjectFactory<HttpMessageConverters> messageConverters)
is deprecated. you should use another constructor:
public SpringDecoder(ObjectFactory<HttpMessageConverters> messageConverters,
ObjectProvider<HttpMessageConverterCustomizer> customizers)
for example:
@Bean
public Decoder feignDecoder(ObjectProvider<HttpMessageConverterCustomizer> customizers) {
// HttpMessageConverter<?> jacksonConverter = new MappingJackson2HttpMessageConverter(customObjectMapper());
// HttpMessageConverters httpMessageConverters = new HttpMessageConverters(jacksonConverter);
var httpMessageConverters = new HttpMessageConverters();
return new ResponseEntityDecoder(new SpringDecoder(() -> httpMessageConverters, customizers));
}
@Bean
public Encoder feignEncoder() {
var httpMessageConverters = new HttpMessageConverters();
return new SpringEncoder(() -> httpMessageConverters);
}
if you want to write a decode time customizer, then you can wright like this:
@Component
public class HttpMessageCustomizer implements HttpMessageConverterCustomizer {
@Override
public void accept(List<HttpMessageConverter<?>> httpMessageConverters) {
//customizing
}
@Override
public Consumer<List<HttpMessageConverter<?>>> andThen(Consumer<? super List<HttpMessageConverter<?>>> after) {
return HttpMessageConverterCustomizer.super.andThen(after);
}
}

- 31
- 4