7

I am using Spring boot 1.5.7-RELEASE.

I am trying to set global non null Jackson property in my application.

but it is not working.

I have tried both in application.properties and bootstrap.properties but not working.

spring.jackson.default-property-inclusion=NON_NULL
spring.jackson.serialization-inclusion=NON_NULL

but when I applied on class level, it is working fine.

@JsonInclude(JsonInclude.NON_NULL)
Ravat Tailor
  • 1,193
  • 3
  • 20
  • 44
  • do you mean https://stackoverflow.com/questions/12813319/enforce-not-null-field-in-json-object? – Ori Marko Jul 10 '18 at 09:38
  • My concern is without annotating the field, through properties file is this possible – Ravat Tailor Jul 10 '18 at 09:45
  • make it lowercase spring.jackson.default-property-inclusion=non_null – Alien Jul 10 '18 at 10:33
  • I was caught by same problem caused by https://stackoverflow.com/questions/45609569/setting-jackson-feature-write-dates-as-timestamps-not-working-in-spring-boot – mrduguo Oct 02 '18 at 10:41
  • @JsonInclude(JsonInclude.Include.NON_NULL), this is not working for me. Spring boot version 2.1.4 – Anurag Sep 25 '19 at 11:59

3 Answers3

7

According to the documentation the correct answer is:

spring.jackson.default-property-inclusion=non_null

(note the lowercase non_null - this may be the cause of your problem)

Edit: I've created a simple Spring Boot 1.5.7.RELEASE project with only the following two compile dependencies:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
</dependency> 

Then I added the following controller and response classes (using Lombok to skip some boilerplate code):

@RestController
@RequestMapping("/jackson")
public class JacksonTestController {

    @GetMapping("/test")
    public Response test() {
        val response = new Response();
        response.setField1("");

        return response;
    }
}

@Data
class Response {
    private String field1;
    private String field2;
    private Integer field3;
}

Finally I configured Jackson as per documentation, run the application and navigated to http://localhost:8080/jackson/test. The result was (as expected):

{"field1":""}

After that I dug into Spring Boot's source code and discovered that Spring uses class org.springframework.http.converter.json.Jackson2ObjectMapperBuilder to create instances of com.fasterxml.jackson.databind.ObjectMapper. I then put a breakpoint in method public <T extends ObjectMapper> T build() of aforementioned builder class and run my application in debug mode.

I discovered that there are 8 instances of ObjectMapper created during application startup and only one of them is configured using contents of application.properties file. The OP never specified how exactly he was using the serialization, so it's possible his code referred to one of the other 7 object mappers available.

At any rate, the only way to ensure that all object mappers in the application are configured to serialize only non-null properties is to create one's own copy of class org.springframework.http.converter.json.Jackson2ObjectMapperBuilder and etiher hard code that option as default or customize the class to read application.properties during every call to it's constructor or build method.

Konrad Botor
  • 4,765
  • 1
  • 16
  • 26
  • My version seems to prefer NON_NULL – Half_Duplex Sep 04 '19 at 01:39
  • Hey how did you figure out that there are 8 instances of ObjectMapper? Is there a way do debug how many instances of a certain object are there at runtime using Intellij or Eclipse? Thanks – theprogrammer May 17 '20 at 14:20
  • I wrote that in my response: "After that I dug into Spring Boot's source code and discovered that Spring uses class org.springframework.http.converter.json.Jackson2ObjectMapperBuilder to create instances of com.fasterxml.jackson.databind.ObjectMapper. I then put a breakpoint in method public T build() of aforementioned builder class and run my application in debug mode." – Konrad Botor May 18 '20 at 08:02
4

Maybe I'm late to the party but It may help someone.

Extend WebMvcConfigurationSupport class and customize the Springboot configuration the way you want.

@Configuration
public class Config extends WebMvcConfigurationSupport{

    @Override
    protected void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        ObjectMapper mapper = new ObjectMapper();
        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        converter.setObjectMapper(mapper);
        converters.add(converter);
        super.configureMessageConverters(converters);
    }
}
0

I was just dealing with the settings in application.properties not taking either. In my case, there was an abstract config class I was extending which defined an ObjectMapper bean that had totally different settings. So I had to override it.

What brought me to the place of finding that was using the /beans Actuator endpoint that Spring Boot apps have, and searching for 'ObjectMapper'. It revealed an instance I didn't realize was being created.

amdg
  • 2,211
  • 1
  • 14
  • 25
jeremy simon
  • 601
  • 1
  • 8
  • 19