38

I'm trying to output an OffsetDateTime from my Spring application, and have in my application.properties these properties:

spring.jackson.serialization.WRITE_DATES_AS_TIMESTAMPS=false
spring.jackson.date-format=yyyy-MM-dd'T'HH:mm

However when the date is returned it is formatted as

"2017-01-30T16:55:00Z"

How should I correctly configure the format for the date in my Spring application?

Dave
  • 788
  • 1
  • 6
  • 11

7 Answers7

31

So I've managed to figure out a solution, but if you have an alternative please post it.

I ended up creating a new primary ObjectMapper bean, and registering a new module with a custom serializer for OffsetDateTime. I'm able to set my own date format in here, using java.time.format.DateTimeFormatter. I also had to register the JavaTimeModule with my mapper.

@Configuration
public class JacksonOffsetDateTimeMapper{

    @Primary
    @Bean
    public ObjectMapper objectMapper() {

        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.registerModule(new JavaTimeModule());
        SimpleModule simpleModule = new SimpleModule();
        simpleModule.addSerializer(OffsetDateTime.class, new JsonSerializer<OffsetDateTime>() {
            @Override
            public void serialize(OffsetDateTime offsetDateTime, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException, JsonProcessingException {
                jsonGenerator.writeString(DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(offsetDateTime));
            }
        });
        objectMapper.registerModule(simpleModule);

        return objectMapper;
    }

}
Dave
  • 788
  • 1
  • 6
  • 11
29
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);

By doing that, you can get OffsetDateTime properties as ISO 8601 including offset in your target.

Utku A.
  • 738
  • 8
  • 8
  • Although the accepted answer worked, this also works for me and is much more concise. Of note, I'm just using Jackson in an AWS Lambda, so it's not in Spring and doesn't have any of the framework/Beans/auto-config/etc. – Steve Goossens Oct 31 '20 at 00:48
7

Adding a dependency on jackson-modules-java8 worked for me (jackson-datatype-jsr310 is deprecated)

<!-- deserialize Java 8 date time types e.g OffsetDateTime --> 
<dependency> 
  <groupId>com.fasterxml.jackson.module</groupId>
  <artifactId>jackson-modules-java8</artifactId>
</dependency>

I also needed to add this for it to work:

 om.registerModule(new JavaTimeModule());

No need for the write-dates-as-timestamps=false or om.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) - that is applicable for Java "Date" object.

I used this annotation:

 @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX")  

and get output like this:

"timestamp":"2020-04-23T08:00:00.000-06:00"

LeslieM
  • 2,105
  • 1
  • 17
  • 8
  • 2
    You didn't actually need to register the module manually like that; you just needed to add a JavaTimeModule bean to your application context and boot would have done it for you: `Any beans of type com.fasterxml.jackson.databind.Module are automatically registered with the auto-configured Jackson2ObjectMapperBuilder and are applied to any ObjectMapper instances that it creates. This provides a global mechanism for contributing custom modules when you add new features to your application.` – Roddy of the Frozen Peas Aug 08 '20 at 23:35
  • 2
    `Note that as of 2.6, this module does NOT support auto-registration, because of existence of legacy version, JSR310Module. Legacy version has the same functionality, but slightly different default configuration: see JSR310Module for details.` – PhilBa Nov 03 '21 at 11:38
  • Also you still need to disable `SerializationFeature.WRITE_DATES_AS_TIMESTAMPS` – PhilBa Nov 03 '21 at 11:39
4
  1. Add jackson-datatype-jsr310 to your dependencies
  2. Add to application.properties:

    spring.jackson.serialization.write-dates-as-timestamps=false
    

You will get:

"lastUpdated": "2017-07-16T19:17:57.689Z"
Konstantin Pavlov
  • 956
  • 1
  • 10
  • 24
3

The spring property doesn't work for me as well. Setting the property to ObjectMapper works for me though.

objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
danny
  • 3,046
  • 3
  • 23
  • 28
1

Have you tried put @JsonFormat(pattern="dd/MM/yyyy HH:mm:ss Z") before your field?

@JsonProperty("timestamp")
@JsonFormat(pattern="yyyy-MM-dd'T'HH:mm")
private OffsetDateTime timestamp;

I guess you will get:

2017-01-30'T'16:55
WesternGun
  • 11,303
  • 6
  • 88
  • 157
0

Removing @EnableWebMvc and just inheriting from WebMvcConfigurerAdapter helped me not to overwrite the ObjectMapper config, so that the configuration properties specified in the application.yml are applied.

adlerer
  • 1,010
  • 11
  • 14