The Spring Boot insist on serializing my ZonedDateTime
type data as a floating-point timestamp in seconds. I have tried all the methods online, but none of them could make it give up.
To be precise, the rest controller always serializes ZonedDateTime
type fields as floating-point timestamps in seconds.
I have tried most of the solutions available online, which do allow me to manually inject ObjectMapper
and manually serialize to get my custom result, but none of this works for the rest controller. My custom serialization code is not even executed.
I have tried @JsonComponent
, custom ObjectMapper
, and Jackson2ObjectMapperBuilderCustomizer
, but Spring Boot always insists on its own way. It’s really a framework that’s hard to control.
@Configuration
public class JacksonConfig {
// The code was indeed executed, but it didn't work; at least the rest controller ignored me
@Bean
@Primary
public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) {
var objectMapper = builder.build();
SimpleModule module = new SimpleModule("CustomZonedDateTimeModule");
module.addSerializer(ZonedDateTime.class, new ZonedDateTimeTimestampSerializer());
objectMapper.registerModule(module);
return objectMapper;
}
}
@JsonComponent // I have tried @JsonComponent, not work.
public class ZonedDateTimeTimestampSerializer extends JsonSerializer<ZonedDateTime> {
@Override
public void serialize(ZonedDateTime value, JsonGenerator gen, SerializerProvider serializers)
throws IOException {
if (value != null) {
gen.writeNumber(value.toInstant().toEpochMilli());
}
}
}
@Configuration
public class JacksonConfig implements Jackson2ObjectMapperBuilderCustomizer {
// The code was indeed executed, but it didn't work; at least the rest controller ignored me
public void customize(Jackson2ObjectMapperBuilder builder) {
SimpleModule module = new SimpleModule("CustomZonedDateTimeModule");
module.addSerializer(ZonedDateTime.class, new ZonedDateTimeTimestampSerializer());
builder.modules(module);
}
}
@Configuration
public class JacksonConfig {
// The code was indeed executed, but it didn't work; at least the rest controller ignored me
@Bean
@Primary
public JavaTimeModule javaTimeModule() {
var module = new JavaTimeModule();
module.addSerializer(ZonedDateTime.class, new ZonedDateTimeTimestampSerializer());
return module;
}
}
Also, just to mention, I am using WebFlux, not sure if that makes a difference. It's hard to believe that such a seemingly simple issue has stumped me; Spring's black box nature is too severe, and the configuration is overly opaque.
It might really be related to WebFlux, because I am currently not using the traditional REST controller, so I’m not sure if the traditional REST controller has this issue as well. But I guess it probably doesn’t, otherwise there would have been widespread complaints online by now.
@Configuration
@EnableWebFlux
@RequiredArgsConstructor
public class WebConfigure implements WebFluxConfigurer {
private final ObjectMapper objectMapper;
// This is the key point: WebFlux does not use the ObjectMapper managed by Spring, but instead creates its own, which causes all my Jackson configurations to hardly take effect.
@Override
public void configureHttpMessageCodecs(@NonNull ServerCodecConfigurer configurer) {
configurer.defaultCodecs().jackson2JsonEncoder(new Jackson2JsonEncoder(objectMapper));
configurer.defaultCodecs().jackson2JsonDecoder(new Jackson2JsonDecoder(objectMapper));
}
}