'Spring cloud open Feign Not ignoring null Values while Encoding

I am working on a Spring boot application. We are using Spring cloud open Feign for making rest calls. We are using the default GsonEncoder(), but for some reason gson is not excluding the null properties while encoding the payload.

Config:

 return Feign.builder()
                .options(ApiOptions())
                .encoder(new GsonEncoder())
                .decoder(new GsonDecoder())
                .target(ApiClient.class, "URL");

Client:

@FunctionalInterface
@FeignClient(
        value = "apiTest",
        url = "urlHere"
)
public interface ApiClient {
    @PostMapping("path/to/service")
    AiResponse getDetails(ApiRequest apiRequest);
}

ApiRequest.java:

public class ApiRequest {
    private String userName;
    private String userId;
    private String password;

    //@setters and getters
}

But while making the request, the Request Body is :

{
  "userName" : "test,
  "userId" : null,
  "password": "password"
}

My Understanding is that Gson should automatically remove the null while serializing the Request Body. But i can see null properties exist in request.

I even tried with Custom Encoders (Jackson from below): https://github.com/OpenFeign/feign/blob/master/jackson/src/main/java/feign/jackson/JacksonEncoder.java

As per below, it should not include null while serialzing the requestBody, but still i can see null values being passed in request. https://github.com/OpenFeign/feign/blob/master/jackson/src/main/java/feign/jackson/JacksonEncoder.java#L39

Below are the dependencies: Spring clou version : 2020.0.2 org.springframework.cloud:spring-cloud-starter-openfeign io.github.openfeign:feign-gson:9.5.1

Any suggestions would be really helpful. Thanks in Advance.!



Solution 1:[1]

You need to provide OpenFeign with custom Encoder to let it skip nulls. In my case this beans helps me.

@Configuration
public class ExternalApiConfiguration {
    @Bean
    public Feign.Builder feignBuilder() {
        return Feign.builder()
                .contract(new SpringMvcContract());
    }

    @Bean("feignObjectMapper")
    public ObjectMapper feignObjectMapper() {
        final ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        return objectMapper;
    }

    @Bean
    public Encoder feignEncoder(@Qualifier("feignObjectMapper") ObjectMapper objectMapper) {
        HttpMessageConverter jacksonConverter = new MappingJackson2HttpMessageConverter(objectMapper);
        ObjectFactory<HttpMessageConverters> objectFactory = () -> new HttpMessageConverters(jacksonConverter);
        return new SpringEncoder(objectFactory);
    }

And use this configuration if FeignClient

@FeignClient(configuration = ExternalApiConfiguration.class)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1