Search code examples
jsonspring-mvcspring-bootjackson

SpringBoot RestTemplate ignores spring.jackson.serialization.WRITE_DATES_AS_TIMESTAMPS = false


I am working with OffsetDateTime objects.

I want to output this type in ISO format so I've added the aforementioned property to my application.yml and it works fine when I use it in my controller.

@JsonInclude(JsonInclude.Include.NON_NULL)
public class Schedule
{
    private OffsetDateTime time;
    private String mode;
}

Using in my controller:

public ResponseEntity taskManagerTest() {
    Schedule bpTaskManagerRequest = new Schedule();

    return ResponseEntity.status(HttpStatus.CREATED).headers(null).body(bpTaskManagerRequest);
}

Example result when I am returning my object:

{
  "time": "2017-11-12T15:03:05.171Z",
  "mode": "eSetTime"
}

But if I use the same object to send it further using RestTemplate in my Spring service:

    HttpEntity<Schedule> httpEntity = new HttpEntity<>(bpTaskManagerRequest, headers);

    ResponseEntity<String> answer = restTemplate.exchange(bpTaskManagerURL, HttpMethod.POST, httpEntity,
            String.class);

It is serialized as:

{
    "time": 1510498985.171000000,
    "mode": "eSetTime"
}

My RestTemplate is defined as:

@Autowired
private RestTemplate restTemplate;

application.yml snippet:

spring:
    jackson:
        serialization:
            write-dates-as-timestamps: false

build.gradle snippet:

buildscript {
    ext {
        springBootVersion = '1.5.4.RELEASE'
        ext.kotlin_version = '1.1.51'
    }
}
compile('com.fasterxml.jackson.module:jackson-module-parameter-names')
compile('com.fasterxml.jackson.datatype:jackson-datatype-jdk8')
compile('com.fasterxml.jackson.datatype:jackson-datatype-jsr310')

Example project: https://github.com/deepres/OffsetDateTime-with-RestTemplate


Solution

  • Your application is creating its own RestTemplate bean and not applying any customisation to it. This means that it will be use the default message converters and default Jackson configuration, rather than anything that's configured by Spring Boot.

    As described in the reference documentation, Spring Boot provides a RestTemplateBuilder that can be used to create a RestTemplate. It "will ensure that sensible HttpMessageConverters are applied to RestTemplate instances". You can update your example to use it by changing WebConfiguration to the following:

    package com.example.demo;
    
    import com.fasterxml.jackson.databind.ObjectMapper;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.client.RestTemplate;
    import org.springframework.boot.web.client.RestTemplateBuilder;
    
    @Configuration
    public class WebConfiguration {
    
        @Bean
        public RestTemplate getRestTemplate(RestTemplateBuilder builder) {
            return builder.build();
        }
    
    }
    

    With this change in place, the conversion is now consistent:

    2017-11-17 12:35:02.892  INFO 28527 --- [nio-8080-exec-2] com.example.demo.ExampleController       : Rest template: {"label":"test from controller","time":"2017-11-17T12:35:02.821Z"}
    2017-11-17 12:35:02.905  INFO 28527 --- [nio-8080-exec-1] com.example.demo.DemoService             : Object mapper:{"label":"test from controller","time":"2017-11-17T12:35:02.821Z"}