After a lot of searching I tracked down how to stop java.util.Date fields from being serialised into timestamps when converting to JSON responses in my @RestController.
However I cannot get it to work. All the posts I found said to disable the SerializationFeature.WRITE_DATES_AS_TIMESTAMPS feature of the Jackson objet mapper. So I wrote the following code:
public class MVCConfig { @Autowired Jackson2ObjectMapperFactoryBean objectMapper; @PostConstruct public void postConstruct() { this.objectMapper.setFeaturesToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); } }
As I understand it, a config is a bean as well so auto wiring in the object mapper to set additional properties should work. I've used break points and everything looks good with this setup.
However when I serialise a bean with a java.util.Date property in a response to a http query, I'm still getting a time stamp.
Does anyone know why this is not working? It's got me stumped !
After lots of messing around I found that the following code fixed the problem:
public class MVCConfig extends WebMvcConfigurerAdapter { @Override public void extendMessageConverters(List<HttpMessageConverter<?>> converters) { for (HttpMessageConverter<?> converter : converters) { if (converter instanceof MappingJackson2HttpMessageConverter) { MappingJackson2HttpMessageConverter jsonMessageConverter = (MappingJackson2HttpMessageConverter) converter; ObjectMapper objectMapper = jsonMessageConverter.getObjectMapper(); objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); break; } } } }
I'm not sure if there is an easier way to access the Jackson MVC message converter and configure it. But this is working for me.
Yes I agree with @Feyyaz: adding config to the properties/yml file is the way to config the default, contextual (de)serializer, when this is out of your control and only left to be manipulated by Spring context.
See this part of Spring documentation for more details:
https://docs.spring.io/spring-boot/docs/current/reference/html/howto-spring-mvc.html#howto-customize-the-jackson-objectmapper
Citation in case of original link removal:
79.3 Customize the Jackson ObjectMapper
Spring MVC (client and server side) uses
HttpMessageConverters
to negotiate content conversion in an HTTP exchange. If Jackson is on the classpath, you already get the default converter(s) provided byJackson2ObjectMapperBuilder
, an instance of which is auto-configured for you. TheObjectMapper
(orXmlMapper
for Jackson XML converter) instance (created by default) has the following customized properties:
MapperFeature.DEFAULT_VIEW_INCLUSION
is disabledDeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES
is disabledSerializationFeature.WRITE_DATES_AS_TIMESTAMPS
is disabledSpring Boot also has some features to make it easier to customize this behavior. You can configure the
ObjectMapper
andXmlMapper
instances by using the environment. Jackson provides an extensive suite of simple on/off features that can be used to configure various aspects of its processing. These features are described in six enums:| Enum | Property | Values | | - | - | - | |
com.fasterxml.jackson.databind.DeserializationFeature
|spring.jackson.deserialization.<feature_name>
|true
,false
| |com.fasterxml.jackson.core.JsonGenerator.Feature
|spring.jackson.generator.<feature_name>
|true
,false
| |com.fasterxml.jackson.databind.MapperFeature
|spring.jackson.mapper.<feature_name>
|true
,false
| |com.fasterxml.jackson.core.JsonParser.Feature
|spring.jackson.parser.<feature_name>
|true
,false
| |com.fasterxml.jackson.databind.SerializationFeature
|spring.jackson.serialization.<feature_name>
|true
,false
| |com.fasterxml.jackson.annotation.JsonInclude.Include
|spring.jackson.default-property-inclusion
|always
,non_null
,non_absent
,non_default
,non_empty
|For example, to enable pretty print, set
spring.jackson.serialization.indent_output=true
. Note that, thanks to the use of relaxed binding, the case ofindent_output
does not have to match the case of the corresponding enum constant, which isINDENT_OUTPUT
. This environment-based configuration is applied to the auto-configuredJackson2ObjectMapperBuilder
bean and applies to any mappers created by using the builder, including the auto-configuredObjectMapper
bean. The context’sJackson2ObjectMapperBuilder
can be customized by one or moreJackson2ObjectMapperBuilderCustomizer
beans. Such customizer beans can be ordered (Boot’s own customizer has an order of 0), letting additional customization be applied both before and after Boot’s customization. Any beans of typecom.fasterxml.jackson.databind.Module
are automatically registered with the auto-configuredJackson2ObjectMapperBuilder
and are applied to anyObjectMapper
instances that it creates. This provides a global mechanism for contributing custom modules when you add new features to your application. If you want to replace the defaultObjectMapper
completely, either define a@Bean
of that type and mark it as@Primary
or, if you prefer the builder-based approach, define aJackson2ObjectMapperBuilder
@Bean
. Note that, in either case, doing so disables all auto-configuration of theObjectMapper
. If you provide any@Beans
of typeMappingJackson2HttpMessageConverter
, they replace the default value in the MVC configuration. Also, a convenience bean of typeHttpMessageConverters
is provided (and is always available if you use the default MVC configuration). It has some useful methods to access the default and user-enhanced message converters. See the “Section 79.4, “Customize the @ResponseBody Rendering”” section and theWebMvcAutoConfiguration
source code for more details.
(StackOverFlow markdown does not support tables syntax so it is malformatted. Copy-paste this part in Sublime Text and save as .md
to view, or check the original link.)
Examples:
spring: jackson: default-property-inclusion: non_null # to exclude null in json serialization serialization: write-dates-as-timestamps: true # write milliseconds since epoch in the final json
Or:
spring.jackson.default-property-inclusion: non_null # to exclude null in json serialization spring.jackson.serialization.write-dates-as-timestamps: true # write milliseconds since epoch in the final json
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With