【问题标题】:Jackson date-format for OffsetDateTime in Spring BootSpring Boot 中 OffsetDateTime 的杰克逊日期格式
【发布时间】:2017-06-12 01:49:57
【问题描述】:

我正在尝试从我的 Spring 应用程序中输出一个 OffsetDateTime,并在我的 application.properties 中有这些属性:

spring.jackson.serialization.WRITE_DATES_AS_TIMESTAMPS=false
spring.jackson.date-format=yyyy-MM-dd'T'HH:mm

但是,当返回日期时,它的格式为

"2017-01-30T16:55:00Z"

我应该如何正确配置 Spring 应用程序中的日期格式?

【问题讨论】:

  • 那是哪个 Spring Boot 版本?
  • 这是 1.5.6
  • 'date-format' 仅适用于 java.util.Date 对象。
  • 在 Spring Boot 中,全局配置 (application.properties) 中的“spring.jackson.date-format”仅适用于 java.util.Date,不适用于任何 java.time.* 对象。更多详情请参考github.com/spring-projects/spring-boot/issues/9004

标签: java spring spring-boot jackson


【解决方案1】:
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);

通过这样做,您可以获得 ISO 8601 的 OffsetDateTime 属性,包括目标中的偏移量。

【讨论】:

  • 虽然接受的答案有效,但这也适用于我并且更简洁。值得注意的是,我只是在 AWS Lambda 中使用 Jackson,所以它不在 Spring 中,也没有任何 framework/Beans/auto-config/etc。
【解决方案2】:

添加对 jackson-modules-java8 的依赖对我有用(jackson-datatype-jsr310 已弃用)

<!-- deserialize Java 8 date time types e.g OffsetDateTime --> 
<dependency> 
  <groupId>com.fasterxml.jackson.module</groupId>
  <artifactId>jackson-modules-java8</artifactId>
</dependency>

我还需要添加它才能工作:

 om.registerModule(new JavaTimeModule());

不需要 write-dates-as-timestamps=false 或 om.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) - 适用于 Java“日期”对象。

我使用了这个注解:

 @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX")  

然后得到这样的输出:

"时间戳":"2020-04-23T08:00:00.000-06:00"

【讨论】:

  • 您实际上并不需要像那样手动注册模块;您只需将 JavaTimeModule bean 添加到应用程序上下文中,启动就会为您完成:Any beans of type com.fasterxml.jackson.databind.Module are automatically registered with the auto-configured Jackson2ObjectMapperBuilder and are applied to any ObjectMapper instances that it creates. This provides a global mechanism for contributing custom modules when you add new features to your application.
  • Note that as of 2.6, this module does NOT support auto-registration, because of existence of legacy version, JSR310Module. Legacy version has the same functionality, but slightly different default configuration: see JSR310Module for details.
  • 另外你还需要禁用SerializationFeature.WRITE_DATES_AS_TIMESTAMPS
【解决方案3】:

spring 属性也不适用于我。不过,将属性设置为 ObjectMapper 对我有用。

objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);

【讨论】:

    【解决方案4】:

    您是否尝试过将@JsonFormat(pattern="dd/MM/yyyy HH:mm:ss Z") 放在您的字段之前?

    @JsonProperty("timestamp")
    @JsonFormat(pattern="yyyy-MM-dd'T'HH:mm")
    private OffsetDateTime timestamp;
    

    我猜你会得到:

    2017-01-30'T'16:55
    

    【讨论】:

      【解决方案5】:
      1. 将 jackson-datatype-jsr310 添加到您的依赖项中
      2. 添加到 application.properties:

        spring.jackson.serialization.write-dates-as-timestamps=false
        

      你会得到:

      "lastUpdated": "2017-07-16T19:17:57.689Z"
      

      【讨论】:

      • 在 Spring Boot 2.0.0.M7 的 MockMVC 控制器测试中不起作用
      【解决方案6】:

      所以我已经设法找到一个解决方案,但如果你有替代方案,请发布它。

      我最终创建了一个新的主 ObjectMapper bean,并使用 OffsetDateTime 的自定义序列化程序注册了一个新模块。我可以在这里使用java.time.format.DateTimeFormatter 设置我自己的日期格式。我还必须用我的映射器注册JavaTimeModule

      @Configuration
      public class JacksonOffsetDateTimeMapper{
      
          @Primary
          @Bean
          public ObjectMapper objectMapper() {
      
              ObjectMapper objectMapper = new ObjectMapper();
              objectMapper.registerModule(new JavaTimeModule());
              SimpleModule simpleModule = new SimpleModule();
              simpleModule.addSerializer(OffsetDateTime.class, new JsonSerializer<OffsetDateTime>() {
                  @Override
                  public void serialize(OffsetDateTime offsetDateTime, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException, JsonProcessingException {
                      jsonGenerator.writeString(DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(offsetDateTime));
                  }
              });
              objectMapper.registerModule(simpleModule);
      
              return objectMapper;
          }
      
      }
      

      【讨论】:

      • 就我而言,我需要的只是我的 ObjectMapper 上的 .registerModule(new JavaTimeModule())
      • 对于我的情况,只需在我的 ObjectMapper 上的 objectMapper.readValue(...) 之前添加 .registerModule(new JavaTimeModule())
      猜你喜欢
      • 1970-01-01
      • 2014-07-31
      • 2014-08-06
      • 1970-01-01
      • 2012-12-07
      • 1970-01-01
      • 1970-01-01
      • 2021-08-12
      • 1970-01-01
      相关资源
      最近更新 更多