Spring Boot与Jackson一起串行化java.time.LocalDateTime以返回ISO-8601 JSON时间戳? [英] Spring Boot issues serializing java.time.LocalDateTime with Jackson to return ISO-8601 JSON timestamps?

查看:854
本文介绍了Spring Boot与Jackson一起串行化java.time.LocalDateTime以返回ISO-8601 JSON时间戳?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆