Spring Boot与Jackson一起串行化java.time.LocalDateTime以返回ISO-8601 JSON时间戳? [英] Spring Boot issues serializing java.time.LocalDateTime with Jackson to return ISO-8601 JSON timestamps?
问题描述
我正在尝试在spring-boot REST API应用程序中转换一些模型,以使用java 8的 java.time.LocalDateTime
而不是joda的日期时间
。我希望从API调用返回的时间戳遵循 ISO_8601
格式。动机是与Java 8的时间向前兼容(此处更多)。
证明困难的部分是将包含 LocalDateTime
的对象序列化为JSON。
例如,我有以下实体:
// ... misc import
import java.time.LocalDateTime;
import java.time.ZoneOffset;
@Data
@Entity
@Table(name =users)
公共类用户{
@Id @Column
private String id;
@Column
private String name;
@Column
private String email;
@Column
@JsonFormat(pattern =yyyy-MM-dd'T'HH:mm:ss,timezone =UTC)
private java.time。 LocalDateTime createdAt;
public User(String name,String email){
this.id = Utils.generateUUID();
this.createdAt = LocalDateTime.now(ZoneOffset.UTC);
}
}
我还设置了 application.properties
关闭日期作为时间戳杰克逊功能:
spring.jackson.serialization。 WRITE_DATES_AS_TIMESTAMPS = false
我的maven deps:
<依赖性>
< groupId> org.springframework.boot< / groupId>
< artifactId> spring-boot-starter-web< / artifactId>
< version> 1.3.6.RELEASE< / version>
< / dependency>
<依赖>
< groupId> com.fasterxml.jackson.datatype< / groupId>
< artifactId> jackson-datatype-jsr310< / artifactId>
< version> 2.8.1< / version>
< / dependency>
<依赖>
< groupId> org.hibernate< / groupId>
< artifactId> hibernate-core< / artifactId>
< version> 5.0.1.Final< / version>
< / dependency>
最后,我尝试通过控制器检索JSON表示:
@RequestMapping(/ users)
@RestController
public class UserController {
private UserService userService;
@Autowired
public UserController(UserService userService){
this.userService = userService;
}
@RequestMapping(
value =/ {id},
方法= RequestMethod.GET,
产生= MediaType.APPLICATION_JSON_UTF8_VALUE
)
public User getUser(@PathVariable(id)String id){
return userService.findById(id);
}
}
当我实际拨打此端点时,我得到以下异常:
java.lang.NoSuchMethodError:
com.fasterxml.jackson.datatype.jsr310.ser .JSR310FormattedSerializerBase.findFormatOverrides(LCOM / fasterxml /杰克逊/数据绑定/ SerializerProvider; LCOM / fasterxml /杰克逊/数据绑定/的BeanProperty; Ljava /郎/类;)LCOM / fasterxml /杰克逊/注解/ JsonFormat $值;
或者我还配置了应用程序的 ObjectMapper
配置类:
@Configuration
公共类ServiceConfiguration {
@Bean
public ObjectMapper getJacksonObjectMapper(){
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new JavaTimeModule());
objectMapper.configure(
com.fasterxml.jackson.databind.SerializationFeature.WRITE_DATES_AS_TIMESTAMPS,
false
);
返回objectMapper;
}
}
任何线索都将不胜感激。
更新:
原来这是版本不匹配在Spring Boot的Jackson版本和我在 pom.xml
中的版本之间。正如Miloš和Andy所提议的那样,一旦我设置了正确的版本并使用 spring.jackson.serialization.write_dates_as_timestamps = true
运行应用程序,问题就解决了,而无需配置 ObjectMapper
或在我的 LocalDateTime
模型字段中添加注释。
...
< dependencyManagement>
< dependencies>
< dependency>
< groupId> org.springframework.boot< / groupId>
< artifactId> spring-boot-dependencies< / artifactId>
< version> 1.3.6.RELEASE< / version>
< type> pom< / type>
< scope> import< / scope>
< / dependency>
< / dependencies>
< / dependencyManagement>
< dependencies>
<依赖>
< groupId> org.springframework.boot< / groupId>
< artifactId> spring-boot-starter-web< / artifactId>
< version> 1.3.6.RELEASE< / version>
< / dependency>
<依赖>
< groupId> com.fasterxml.jackson.datatype< / groupId>
< artifactId> jackson-datatype-jsr310< / artifactId>
< / dependency>
<依赖>
< groupId> org.hibernate< / groupId>
< artifactId> hibernate-core< / artifactId>
< / dependency>
< / dependencies>
NoSuchMethodError
是因为你正在混合杰克逊的版本。 Spring Boot 1.3.6使用Jackson 2.6.7,你使用2.8.1的 jackson-datatype-jsr310
。
Spring Boot为Jackson提供依赖管理,包括 jackson-datatype-jsr310
,因此你应该从你的pom中删除该版本。如果你想使用不同版本的Jackson,你应该覆盖 jackson.version
属性:
<性状>
< jackson.version> 2.8.1< /jackson.version>
< / properties>
这将确保所有Jackson依赖项具有相同的版本,从而避免版本不匹配的问题。 / p>
如果您愿意,也可以删除配置 ObjectMapper
的Java代码。 Java Time模块将在类路径中自动注册,并在 application.properties
中配置时间戳时编写日期:
spring.jackson.serialization.write-dates-as-timestamps = false
I'm working on converting some models in a spring-boot REST API app to use java 8's java.time.LocalDateTime
instead of joda's DateTime
. I want the timestamps returned from API call to adhere to the ISO_8601
format. Motivation is to be forward compatible with Java 8's time (more here).
The part that's proving difficult is when it comes to serialize an object containing LocalDateTime
to JSON.
For example, I have the following entity:
// ... misc imports
import java.time.LocalDateTime;
import java.time.ZoneOffset;
@Data
@Entity
@Table(name = "users")
public class User {
@Id @Column
private String id;
@Column
private String name;
@Column
private String email;
@Column
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss", timezone = "UTC")
private java.time.LocalDateTime createdAt;
public User(String name, String email) {
this.id = Utils.generateUUID();
this.createdAt = LocalDateTime.now(ZoneOffset.UTC);
}
}
I have also set my application.properties
to turn off the dates as timestamp jackson feature:
spring.jackson.serialization.WRITE_DATES_AS_TIMESTAMPS = false
My maven deps:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>1.3.6.RELEASE</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>2.8.1</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.0.1.Final</version>
</dependency>
Finally, I try to retrieve the JSON representation via controller:
@RequestMapping("/users")
@RestController
public class UserController {
private UserService userService;
@Autowired
public UserController(UserService userService) {
this.userService = userService;
}
@RequestMapping(
value = "/{id}",
method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_UTF8_VALUE
)
public User getUser(@PathVariable("id") String id) {
return userService.findById(id);
}
}
When I actually make a call to this endpoint, I get the following exception:
java.lang.NoSuchMethodError:
com.fasterxml.jackson.datatype.jsr310.ser.JSR310FormattedSerializerBase.findFormatOverrides(Lcom/fasterxml/jackson/databind/SerializerProvider;Lcom/fasterxml/jackson/databind/BeanProperty;Ljava/lang/Class;)Lcom/fasterxml/jackson/annotation/JsonFormat$Value;
Alternately I also configured the app's ObjectMapper
in the configuration class:
@Configuration
public class ServiceConfiguration {
@Bean
public ObjectMapper getJacksonObjectMapper() {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new JavaTimeModule());
objectMapper.configure(
com.fasterxml.jackson.databind.SerializationFeature.WRITE_DATES_AS_TIMESTAMPS,
false
);
return objectMapper;
}
}
Any leads will be greatly appreciated.
UPDATE:
Turns out it was a version mismatch between Spring Boot's Jackson version and the one I had in my pom.xml
. As Miloš and Andy proposed, once I've set the correct version and run the app with spring.jackson.serialization.write_dates_as_timestamps=true
, the issue was resolved, without needing to configure the ObjectMapper
or adding annotations on my LocalDateTime
model fields.
...
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>1.3.6.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>1.3.6.RELEASE</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
</dependency>
</dependencies>
The NoSuchMethodError
is because you are mixing versions of Jackson. Spring Boot 1.3.6 uses Jackson 2.6.7 and you are using 2.8.1 of jackson-datatype-jsr310
.
Spring Boot provides dependency management for Jackson, including jackson-datatype-jsr310
, so you should remove the version from your pom. If you want to use a different version of Jackson, you should override the jackson.version
property:
<properties>
<jackson.version>2.8.1</jackson.version>
</properties>
This will ensure that all your Jackson dependencies have the same version, thereby avoiding problems with mismatched versions.
You can also, if you wish, remove your Java code that's configuring the ObjectMapper
. The Java Time module will be automatically registered when it's in the classpath and writing dates as timestamps can be configured in application.properties
:
spring.jackson.serialization.write-dates-as-timestamps=false
这篇关于Spring Boot与Jackson一起串行化java.time.LocalDateTime以返回ISO-8601 JSON时间戳?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!