问题
I know that there are many posts on Stackoverflow regarding this topic and I'm sure I've read just about all of them, but I am still struggling to get this working and would appreciate any guidance.
This is the Spring Parent and Jackson Dependencies I am using:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
</parent>
<!-- Jackson -->
<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-parameter-names</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jdk8</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
Within my Application Configuration I am trying to use:
@Autowired
void configureJackson(ObjectMapper jackson2ObjectMapper) {
JavaTimeModule timeModule = new JavaTimeModule();
timeModule.addDeserializer(LocalDate.class,
new LocalDateDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
timeModule.addDeserializer(LocalDateTime.class,
new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
timeModule.addSerializer(LocalDate.class,
new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
timeModule.addSerializer(LocalDateTime.class,
new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
jackson2ObjectMapper
.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false)
.setSerializationInclusion(JsonInclude.Include.NON_NULL)
.registerModule(timeModule)
.registerModule(new ParameterNamesModule())
.registerModule(new Jdk8Module())
.registerModule(new JtsModule());
}
This is the model I am testing with. (I am trying to achive the same in 5-6 models).
public class DateRange implements Serializable {
private static final long serialVersionUID = 6412487507434252330L;
private LocalDateTime startTime;
private LocalDateTime endTime;
private LocalDate startDate;
private LocalDate endDate;
// Getters/Setters
I am hoping that I could find an approach that would apply globally without the need for me to annotate each field individually. I was using java.util.Date before, but ran into some issues with other functionality there.
Trying to use these newer (better) date models instead of that old damaged one is causing me a lot of headache over a simple thing.
Update
I changed my configuration to one of the suggested below and came really close to solving this issue.
@Bean
@Primary
public ObjectMapper objectMapper() {
JavaTimeModule timeModule = new JavaTimeModule();
timeModule.addDeserializer(LocalDate.class,
new LocalDateDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
timeModule.addDeserializer(LocalDateTime.class,
new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
timeModule.addSerializer(LocalDate.class,
new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
timeModule.addSerializer(LocalDateTime.class,
new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
return new ObjectMapper()
//.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
.setSerializationInclusion(JsonInclude.Include.NON_NULL)
.registerModule(timeModule)
.registerModule(new ParameterNamesModule())
.registerModule(new Jdk8Module())
.registerModule(new JtsModule());
}
Now the only issue I have is that LocalDateTime is printing timestamps like: "2018-07-26T07:57:12.938" when I need them like: 2018-07-26 07:57:12.
These fields are already in-use today and I need to make this change seamless in a way that doesn't require my API consumers to make any adjustments.
Cassio mentioned that disabling SerializationFeature.WRITE_DATES_AS_TIMESTAMPS will print timestamps in this ISO format, but it's not what I need. I tried to comment out the field in the hopes that it would pickup the custom DateTimeFormatter I am providing, however it has not changed my output.
回答1:
The JavaTimeModule will do the hard work for you. It provides a set of serializers and deserializers for for the java.time types. If the SerializationFeature.WRITE_DATES_AS_TIMESTAMPS is disabled, java.time types will be serialized in standard ISO-8601 string representations.
By default, Spring will provide you with an instance of ObjectMappper created by the Jackson2ObjectMapperBuilder. This instance is auto-configured for you. See the class documentation for details.
If you want to replace the default ObjectMapper completely, either define a @Bean of that type and mark it as @Primary:
@Bean
@Primary
public ObjectMapper objectMapper() {
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
return mapper;
}
Or, if you prefer the builder-based approach, define a Jackson2ObjectMapperBuilder @Bean.
@Bean
public Jackson2ObjectMapperBuilder objectMapperBuilder() {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
builder.modules(new JavaTimeModule());
builder.featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
return builder;
}
Note that, in either case, doing so disables all auto-configuration of the ObjectMapper. See the documentation for details.
回答2:
I finally got this working with the help of Cassio and some other digging on the web. Looking back I think the issue was that I was defining the custom formats on the JavaTimeModule, but I needed to define them on the mapper instead.
@Bean
public Jackson2ObjectMapperBuilder objectMapperBuilder() {
return new Jackson2ObjectMapperBuilder()
.createXmlMapper(false)
.indentOutput(true)
.featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
.serializers(
new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")),
new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")))
.deserializers(
new LocalDateDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")),
new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")))
.modules(
new JavaTimeModule(),
new ParameterNamesModule(),
new Jdk8Module(),
new JtsModule());
}
https://github.com/spring-projects/spring-boot/issues/4217
http://www.baeldung.com/jackson-serialize-dates
回答3:
You can also solve this to expose this instance:
@Bean
public Jackson2ObjectMapperBuilder configureObjectMapper() {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
builder.modules(new JavaTimeModule(),new ParameterNamesModule(),new Jdk8Module());
builder.featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
return builder;
}
来源:https://stackoverflow.com/questions/51527794/how-do-i-configure-jackson-serialization-on-localdatetime-and-localdate-for-java