Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Boot Jackson date format

I have a problem with Jackson in SpringBoot. My controller returns dates in format yyyy-MM-dd'T'HH:mm:ss'Z', but I need yyyy-MM-dd'T'HH:mm:ss.SSS'Z' (for mwl-calendar in angular which uses date-fns library).

Controller:

@GetMapping(value = "/slots", produces = MediaType.APPLICATION_JSON_VALUE)
public Set<SlotResponse> timeSlots() {
    return slotService.getSlots();
}

SlotResponse:

@Data
public class SlotResponse {
    private Instant start;
    private Instant end;
}

Additional dependency:

<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-jsr310</artifactId>
</dependency>

I tried:

  1. to use @JsonFormat(pattern="yyyy-MM-dd'T'HH:mm:ss.SSS'Z'") annotation
  2. to use spring.jackson.date-format=yyyyMMddTHH:mm:ss.SSSZ configuration
  3. to create ObjectMapper manually:
@Bean
public ObjectMapper objectMapper() {
    ObjectMapper mapper = new ObjectMapper();
    mapper.registerModule(new JavaTimeModule());
    mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
    mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"));
    return mapper;
}
  1. to enable options SerializationFeature.WRITE_DATES_WITH_ZONE_ID and SerializationFeature.WRITE_DATES_WITH_CONTEXT_TIME_ZONE

But all of this didn't take effect. Everytime I see this result:

[{"start":"2023-05-11T16:00:00Z","end":"2023-05-11T17:00:00Z"}]

I use Java 17, SpringBoot 2.7.0, Jackson 2.13.3

What is wrong?

like image 965
Virkom Avatar asked Mar 07 '26 21:03

Virkom


1 Answers

You can create custom json serializer for Instant type:

    public static class InstantSerializer extends StdSerializer<Instant> {

        public InstantSerializer() {
            super(Instant.class);
        }

        @Override
        public void serialize(
            @Nullable final Instant value,
            @NonNull final JsonGenerator jsonGenerator,
            @NonNull final SerializerProvider serializerProvider
        ) throws IOException {
            if (value != null) {
                final DateTimeFormatter formatter = DateTimeFormatter
                    .ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
                    .withZone(ZoneId.systemDefault());
                final String text = formatter.format(value);
                jsonGenerator.writeString(text);
            }
        }

    }

Then use it on the field that you want to follow the format:

    @Data
    public class SlotResponse {

        @JsonSerialize(using = InstantSerializer.class) // Add this
        
        private Instant start;
        @JsonSerialize(using = InstantSerializer.class) // Add this
        private Instant end;
    }

In case you want to make this apply for your whole system, you can add the serializer to jackson:

    @Bean
    public ObjectMapper objectMapper() {
        ObjectMapper mapper = new ObjectMapper();
        ...
        final SimpleModule module = new SimpleModule();
        module.addSerializer(new InstantSerializer());
        mapper.registerModule(module);
        ...
        return mapper;
    }

like image 74
Ananta Avatar answered Mar 09 '26 09:03

Ananta