我有一个包含Java 8日期时间类型字段的实体。问题是这些字段被序列化为对象。我添加了jackson-datatype-jsr310
依赖项,因此Spring Boot 1.5.7会自动配置处理Java 8日期时间类型的JavaTimeModule
。似乎模块没有注册(我在JavaTimeModule构造函数中放了一个断点)。我知道我不需要自定义ObjectMapper
。我花了几个小时阅读这个问题,解决方案总是添加jackson-datatype-jsr310
依赖项,但在我的情况下它不起作用。
实体:
@Entity
public class DateTimeEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private LocalDate localDate;
private LocalDateTime localDateTime;
private Instant instant;
private OffsetDateTime offsetDateTime;
private ZonedDateTime zonedDateTime;
}
RestController方法:
@GetMapping("/datetimes/{id}")
public ResponseEntity<DateTimeEntity> getById(@PathVariable Long id) {
DateTimeEntity dateTimeEntity = dateTimeRepository.findOne(id);
return new ResponseEntity<DateTimeEntity>(dateTimeEntity, HttpStatus.OK);
}
返回JSON对象:
{
"id": 1,
"localDate": null,
"localDateTime": null,
"instant": {
"epochSecond": 1508772600,
"nano": 0
},
"offsetDateTime": {
"offset": {
"totalSeconds": 0,
"id": "Z",
"rules": {
"fixedOffset": true,
"transitionRules": [],
"transitions": []
}
},
"dayOfMonth": 23,
"dayOfWeek": "MONDAY",
"dayOfYear": 296,
"month": "OCTOBER",
"monthValue": 10,
"year": 2017,
"hour": 15,
"minute": 30,
"nano": 0,
"second": 0
},
"zonedDateTime": {
"offset": {
"totalSeconds": 0,
"id": "Z",
"rules": {
"fixedOffset": true,
"transitionRules": [],
"transitions": []
}
},
"zone": {
"totalSeconds": 0,
"id": "Z",
"rules": {
"fixedOffset": true,
"transitionRules": [],
"transitions": []
}
},
"dayOfMonth": 23,
"dayOfWeek": "MONDAY",
"dayOfYear": 296,
"month": "OCTOBER",
"monthValue": 10,
"year": 2017,
"hour": 15,
"minute": 30,
"nano": 0,
"second": 0,
"chronology": {
"id": "ISO",
"calendarType": "iso8601"
}
}
}
POM文件:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>framework-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.7.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
<mockito.version>2.11.0</mockito.version>
<org.mapstruct.version>1.2.0.Final</org.mapstruct.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-jdk8</artifactId>
<version>${org.mapstruct.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>${jackson.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<annotationProcessorPaths>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${org.mapstruct.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
<plugin>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctor-maven-plugin</artifactId>
<version>1.5.5</version>
<executions>
<execution>
<id>output-html</id>
<phase>generate-resources</phase>
<goals>
<goal>process-asciidoc</goal>
</goals>
<configuration>
<backend>html</backend>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
答案 0 :(得分:1)
根据How to customize ObjectMapper:
任何类型为com.fasterxml.jackson.databind.Module的bean都将是 自动注册自动配置 Jackson2ObjectMapperBuilder并应用于任何ObjectMapper实例 它创造了。这提供了一种全球性的贡献机制 向应用程序添加新功能时的自定义模块。
仅添加依赖是不够的,您必须声明一个@Bean
模块,如下所示:
@Bean
public Module dateTimeModule(){
return new new JavaTimeModule();
}
不推荐使用 Plus jackson-datatype-jsr310
模块,而应使用JavaTimeModule。
答案 1 :(得分:1)
解决方案是将依赖项添加到类路径中。出于某种原因,它不在IDE中。
即使不推荐使用依赖项,它仍然由spring-boot-autoconfigure
模块使用。见Spring Boot Code
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
当它在类路径中时,Java 8日期和时间对象被序列化为时间戳。
答案 2 :(得分:0)
我在将 spring boot 从 2.3.7 升级到 2.5.1 时开始遇到这个问题。
如果您定义了 ObjectMapper @Bean,那么您需要使用它注册时间模块。
@Bean
public ObjectMapper defaultMapper() {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new JavaTimeModule());
return objectMapper;
}
很多时候,编码人员在使用 jackson 序列化时只会创建一个“new ObjectMapper()”,因此请注意使用 vanilla mapper,而不是自动装配已注册时间模块的预配置默认值。
如前所述,您将需要 jackson-datatype-jsr310,但这已作为托管版本包含在 Spring Boot 中。
如果你没有手动定义对象映射器 bean,那么 Spring Boot 应该会自动提供一个注册了时间模块的对象。