Reputation: 15951
I am working with spring-boot 2.5.4 and trying to set default-property-inclusion=non_null
globally, so that null values no longer show up in my spring web server's responses.
I have configured spring.jackson.default-property-inclusion=non_null
in my project's application.yml
as described in an earlier question.
spring:
jackson:
default-property-inclusion: non_null
Unfortunately, null-values are still included in my controller's output:
{
"enabled": true,
"name": "foo",
"subdomain": null,
"tenantId": null
}
What works however is if I add non-null directly to my dto:
@Data
@NoArgsConstructor
@JsonInclude(Include.NON_NULL)
public class GlobalTenantGet {
private UUID tenantId;
private String name;
private String subdomain;
private boolean enabled;
}
yielding
{
"enabled": true,
"name": "foo"
}
as expected.
Why does configuring @JsonInclude
locally on the dto cause the null properties to disappear as expected but why does configuring spring.jackson.default-property-inclusion=non_null
not have the same effect?
Setting a breakpoint in org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration.JacksonObjectMapperConfiguration#jacksonObjectMapper
shows, that the properties configured in application.yaml
really made it to jackson:
ObjectMapper
in the controllerI get the expected behavior when autowiring the ObjectMapper
in my controller and serializing my object directly via objectMapper.writeValueAsString()
.
ObjectMapper
These are mostly in reply to Pawel Woroniecki's answer
I have a
@Configuration
public class ObjectMapperConfiguration {
@Primary
@Bean
public ObjectMapper objectMapper() {
final var om = new ObjectMapper();
om.setSerializationInclusion(Include.NON_NULL);
return om;
}
}
still includes null properties in the output
Jackson2ObjectMapperBuilder
with serializationInclusion
@Configuration
public class ObjectMapperConfiguration {
@Bean
public Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder() {
return new Jackson2ObjectMapperBuilder().serializationInclusion(JsonInclude.Include.NON_NULL);
}
}
still yields
{
"enabled": true,
"name": "foo",
"subdomain": null,
"tenantId": null
}
MappingJackson2HttpMessageConverter
@Configuration
public class ObjectMapperConfiguration {
@Bean
public MappingJackson2HttpMessageConverter messageMappingConverter() {
final var om = new ObjectMapper();
om.setSerializationInclusion(Include.NON_NULL);
return new MappingJackson2HttpMessageConverter(om);
}
}
still no bueno :-(
Upvotes: 3
Views: 5233
Reputation: 15951
It seems @EnableWebMvc
is the culprit. I have a WebMvcConfigurer
that looks like this:
@Configuration
@EnableWebMvc // <----- this is the culprit!
public class WebConfiguration implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedMethods("OPTIONS", "GET", "POST", "PUT", "PATCH", "DELETE")
.allowedOrigins("example.com")
.allowedHeaders("*");
}
@Bean
public KeycloakSpringBootConfigResolver KeycloakConfigResolver() {
return new KeycloakSpringBootConfigResolver();
}
@Bean
public InternalResourceViewResolver defaultViewResolver() {
return new InternalResourceViewResolver();
}
}
commenting out @EnableWebMvc
allows everything to work as expected.
Upvotes: 9
Reputation: 519
There are several possible approaches to solve this issue and some of them are clearly explained here: https://www.baeldung.com/spring-boot-customize-jackson-objectmapper
Generally you can:
Override default ObjectMapper
by creating custom ObjectMapper
bean and marking it as @Primary
(the simplest way but heavily impacts your application as all ObjectMapper
instances you inject in code will use this one by default which may be good or not for you)
Define custom bean for Jackson2ObjectMapperBuilder
and set proper serializationInclusion
on this builder.
Register custom HTTP message converter in Spring which will use custom ObjectMapper by defining bean for MappingJackson2HttpMessageConverter
(constructor of this converter accepts ObjectMapper
so you can pass properly configured mapper there)
Upvotes: 1