【问题标题】:JSON Java 8 LocalDateTime format in Spring BootSpring Boot 中的 JSON Java 8 LocalDateTime 格式
【发布时间】:2015-07-09 11:21:40
【问题描述】:

在我的 Spring Boot 应用程序中格式化 Java 8 LocalDateTime 时遇到了一个小问题。使用“正常”日期我没有问题,但 LocalDateTime 字段转换为以下内容:

"startDate" : {
    "year" : 2010,
    "month" : "JANUARY",
    "dayOfMonth" : 1,
    "dayOfWeek" : "FRIDAY",
    "dayOfYear" : 1,
    "monthValue" : 1,
    "hour" : 2,
    "minute" : 2,
    "second" : 0,
    "nano" : 0,
    "chronology" : {
      "id" : "ISO",
      "calendarType" : "iso8601"
    }
  }

虽然我想将其转换为:

"startDate": "2015-01-01"

我的代码如下所示:

@JsonFormat(pattern="yyyy-MM-dd")
@DateTimeFormat(iso = DateTimeFormat.ISO.TIME)
public LocalDateTime getStartDate() {
    return startDate;
}

但是上述任何一个注释都不起作用,日期一直像上面那样格式化。欢迎提出建议!

【问题讨论】:

    标签: java json java-8 spring-boot java-time


    【解决方案1】:

    更新:Spring Boot 2.x 不再需要此配置。我写了a more up to date answer here


    (这是 Spring Boot 2.x 之前的做法,可能对使用旧版本 Spring Boot 的人有用)

    终于找到here怎么办了。要修复它,我需要另一个依赖项:

    compile("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.4.0")
    

    通过包含此依赖项,Spring 将自动为其注册转换器,如 here 所述。之后,您需要在 application.properties 中添加以下内容:

    spring.jackson.serialization.write_dates_as_timestamps=false
    

    这将确保使用正确的转换器,并且日期将以2016-03-16T13:56:39.492 的格式打印

    只有在您想更改日期格式时才需要注释。

    【讨论】:

    • 可能值得包括以下注释 - @JsonSerialize(using = LocalDateTimeSerializer.class)...
    • 按照@patelb answer的建议,最好只使用application.properties 条目。
    • 不工作。但是 patelib 的答案开箱即用!
    • 提醒一下,我们需要尼克提到的@JsonSerialize 注释才能使其正常工作。
    • 在我的情况下这有效:@JsonSerialize(using = LocalDateSerializer.class)@JsonFormat(pattern="yyyy-MM-dd"),没有新的依赖项和属性。
    【解决方案2】:

    这对我有用。

    我在我的 DTO 中定义了 birthDate 字段,如下所述:

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
        private LocalDateTime birthDate;
    

    在我的请求正文中,我以以下格式传递了 birthDate

    {
       "birthDate": "2021-06-03 00:00:00"
     }
    

    【讨论】:

      【解决方案3】:

      添加

      group: 'com.fasterxml.jackson.datatype', name: 'jackson-datatype-jsr310', version: '2.8.8'
      

      进入gradle编译块

      application.yml 文件中

      spring:
        jackson:
          serialization:
            write_dates_as_timestamps: false
      

      如果您使用的是application.properties 文件 添加以下内容

      spring.jackson.serialization.write_dates_as_timestamps=false
      

      如果您想应用自定义格式,您可以应用注释

          @JsonFormat(pattern = "yyyy-MMMM-dd hh:mm:ss")
          private LocalDateTime date;
      

      它开始对我很好

      【讨论】:

        【解决方案4】:

        这对我有用。

        import com.fasterxml.jackson.annotation.JsonFormat;
        import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
        import com.fasterxml.jackson.databind.annotation.JsonSerialize;
        import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
        import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
        public Class someClass {
        
            @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
            @JsonSerialize(using = LocalDateTimeSerializer.class)
            @JsonDeserialize(using = LocalDateTimeDeserializer.class)
            private LocalDateTime sinceDate;
        
        }
        
        

        【讨论】:

          【解决方案5】:

          我添加了com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.6.1 依赖并开始获取以下格式的日期:

          "birthDate": [
              2016,
              1,
              25,
              21,
              34,
              55
            ]
          

          这不是我想要的,但我越来越近了。然后我添加了以下内容

          spring.jackson.serialization.write_dates_as_timestamps=false
          

          到 application.properties 文件,它为我提供了我需要的正确格式。

          "birthDate": "2016-01-25T21:34:55"
          

          【讨论】:

          • 在包含 jackson-datatype-jsr310 依赖项时开箱即用。这应该是公认的答案。
          • 仅供参考,如果您使用以下方式配置 ObjectMapper,则 application.properties 部分可以通过 Java 配置完成:mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
          【解决方案6】:

          我使用的是 Spring Boot 2.1.8。我已经导入了

          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-json</artifactId>
          </dependency>
          

          其中包括 jackson-datatype-jsr310

          然后,我必须添加这些注释

          @JsonSerialize(using = LocalDateTimeSerializer.class)
          @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
          @JsonProperty("date")
          LocalDateTime getDate();
          

          它有效。 JSON 如下所示:

          "date": "2020-03-09 17:55:00"
          

          【讨论】:

          • 提示:仅当缺少spring-boot-starter-web 时才需要包含spring-boot-starter-json
          【解决方案7】:

          我使用的是 Springboot 2.0.6,由于某种原因,应用程序 yml 更改不起作用。 而且我还有更多的要求。

          我尝试创建 ObjectMapper 并将其标记为 Primary,但 Spring Boot 抱怨我已经将 jacksonObjectMapper 标记为 Primary!

          所以这就是我所做的。 我对内部映射器进行了更改。

          我的序列化器和反序列化器是特殊的——它们处理'dd/MM/YYYY';并且在反序列化时 - 它会尽力使用 3-4 种流行格式来确保我有一些 LocalDate。

          @Autowired
          ObjectMapper mapper;
          
          @PostConstruct
          public ObjectMapper configureMapper() {
              mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
              mapper.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
          
              mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
              mapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true);
          
              mapper.configure(MapperFeature.ALLOW_COERCION_OF_SCALARS, true);
              mapper.configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true);
          
              SimpleModule module = new SimpleModule();
              module.addDeserializer(LocalDate.class, new LocalDateDeserializer());
              module.addSerializer(LocalDate.class, new LocalDateSerializer());
              mapper.registerModule(module);
          
              return mapper;
          }
          

          【讨论】:

            【解决方案8】:

            简单地使用:

            @JsonFormat(pattern="10/04/2019")
            

            或者您可以随意使用模式,例如:('-' in place of '/')

            【讨论】:

            • 这个答案之前已经分享过,但后来使用了正确的语法。
            【解决方案9】:

            如前所述,spring-boot 将获取您需要的所有内容(对于 web 和 webflux starter)。

            但更好的是 - 您不需要自己注册任何模块。 看看here。由于@SpringBootApplication 在后台使用@EnableAutoConfiguration,这意味着JacksonAutoConfiguration 将自动添加到上下文中。 现在,如果您查看JacksonAutoConfiguration 内部,您会看到:

                private void configureModules(Jackson2ObjectMapperBuilder builder) {
                    Collection<Module> moduleBeans = getBeans(this.applicationContext,
                            Module.class);
                    builder.modulesToInstall(moduleBeans.toArray(new Module[0]));
                }
            

            This fella 将在初始化过程中被调用,并将获取它可以在类路径中找到的所有模块。 (我用的是 Spring Boot 2.1)

            【讨论】:

              【解决方案10】:

              写下这个答案也是为了提醒我。

              我在这里结合了几个答案,最后我的答案是这样的。 (我使用的是 SpringBoot 1.5.7 和 Lombok 1.16.16)

              @Data
              public Class someClass {
              
                 @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
                 @JsonSerialize(using = LocalDateTimeSerializer.class)
                 @JsonDeserialize(using = LocalDateTimeDeserializer.class)
                 private LocalDateTime someDate;
              
              }
              

              【讨论】:

              • 您可能想要为DateTimeFormat 和其他人添加导入。
              • LocalDateTimeDeserializer 从何而来?
              • 您可以检查 Erik Pragt 接受的答案,他提到他添加了杰克逊依赖项,这就是它的来源。希望它能回答你的问题
              • 这解决了我的问题,谢谢。
              • 很高兴它帮助了交配
              【解决方案11】:

              它在 maven 中,具有属性,因此您可以在 Spring Boot 升级之间生存

              <dependency>
                      <groupId>com.fasterxml.jackson.datatype</groupId>
                      <artifactId>jackson-datatype-jsr310</artifactId>
                      <version>${jackson.version}</version>
              </dependency>
              

              【讨论】:

              • 将此解决方案与@NickGrealy 评论一起使用:可能值得包含以下注释 - @JsonSerialize(using = LocalDateTimeSerializer.class)
              【解决方案12】:

              @JsonDeserialize(using= LocalDateDeserializer.class) 不适用于以下依赖项。

              <dependency>
                  <groupId>com.fasterxml.jackson.datatype</groupId>
                  <artifactId>jackson-datatype-jsr310</artifactId>
                  <version> 2.9.6</version>
              </dependency>
              

              我使用下面的代码转换器将日期反序列化为java.sql.Date

              import javax.persistence.AttributeConverter;
              import javax.persistence.Converter;
              
              
              @SuppressWarnings("UnusedDeclaration")
              @Converter(autoApply = true)
              public class LocalDateConverter implements AttributeConverter<java.time.LocalDate, java.sql.Date> {
              
              
                  @Override
                  public java.sql.Date convertToDatabaseColumn(java.time.LocalDate attribute) {
              
                      return attribute == null ? null : java.sql.Date.valueOf(attribute);
                  }
              
                  @Override
                  public java.time.LocalDate convertToEntityAttribute(java.sql.Date dbData) {
              
                      return dbData == null ? null : dbData.toLocalDate();
                  }
              }
              

              【讨论】:

                【解决方案13】:

                这项工作很好:

                添加依赖:

                <dependency>
                    <groupId>com.fasterxml.jackson.datatype</groupId>
                    <artifactId>jackson-datatype-jdk8</artifactId>
                </dependency>
                

                添加注释:

                @JsonFormat(pattern="yyyy-MM-dd")
                

                现在,你必须得到正确的格式。

                要使用对象映射器,您需要注册 JavaTime

                ObjectMapper mapper = new ObjectMapper();
                mapper.registerModule(new JavaTimeModule());
                

                【讨论】:

                  【解决方案14】:

                  我找到了另一种解决方案,您可以将其转换为您想要的任何格式并应用于所有 LocalDateTime 数据类型,您不必在每个 LocalDateTime 数据类型上方指定 @JsonFormat。 首先添加依赖:

                  <dependency>
                      <groupId>com.fasterxml.jackson.datatype</groupId>
                      <artifactId>jackson-datatype-jsr310</artifactId>
                  </dependency>
                  

                  添加以下 bean:

                  @Configuration
                  public class Java8DateTimeConfiguration {
                      /**
                       * Customizing
                       * http://docs.spring.io/spring-boot/docs/current/reference/html/howto-spring-mvc.html
                       *
                       * Defining a @Bean of type Jackson2ObjectMapperBuilder will allow you to customize both default ObjectMapper and XmlMapper (used in MappingJackson2HttpMessageConverter and MappingJackson2XmlHttpMessageConverter respectively).
                       */
                      @Bean
                      public Module jsonMapperJava8DateTimeModule() {
                          val bean = new SimpleModule();
                  
                          bean.addDeserializer (ZonedDateTime.class, new JsonDeserializer<ZonedDateTime>() {
                              @Override
                              public ZonedDateTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
                                  return ZonedDateTime.parse(jsonParser.getValueAsString(), DateTimeFormatter.ISO_ZONED_DATE_TIME);
                              }
                          });
                  
                          bean.addDeserializer(LocalDateTime.class, new JsonDeserializer<LocalDateTime>() {
                              @Override
                              public LocalDateTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
                                  return LocalDateTime.parse(jsonParser.getValueAsString(), DateTimeFormatter.ISO_LOCAL_DATE_TIME);
                              }
                          });
                  
                          bean.addSerializer(ZonedDateTime.class, new JsonSerializer<ZonedDateTime>() {
                              @Override
                              public void serialize(
                                      ZonedDateTime zonedDateTime, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)
                                      throws IOException {
                                  jsonGenerator.writeString(DateTimeFormatter.ISO_ZONED_DATE_TIME.format(zonedDateTime));
                              }
                          });
                  
                          bean.addSerializer(LocalDateTime.class, new JsonSerializer<LocalDateTime>() {
                              @Override
                              public void serialize(
                                      LocalDateTime localDateTime, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)
                                      throws IOException {
                                  jsonGenerator.writeString(DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(localDateTime));
                              }
                          });
                  
                          return bean;
                      }
                  }
                  

                  在您的配置文件中添加以下内容:

                  @Import(Java8DateTimeConfiguration.class)
                  

                  这将对所有属性 LocalDateTime 和 ZonedDateTime 进行序列化和反序列化,只要您使用的是 spring 创建的 objectMapper。

                  您获得的 ZonedDateTime 格式为:“2017-12-27T08:55:17.317+02:00[Asia/Jerusalem]” 对于 LocalDateTime 是:“2017-12-27T09:05:30.523”

                  【讨论】:

                  • 可能你需要将 val bean 替换为 SimpleModule bean = new SimpleModule();
                  • 这是为 Java 9 设计的吗?
                  • @DanielDai 这是在 Java 8 中。
                  • @Abhi, SimpleModule 扩展 ModuleModule 是一个摘要。 val bean = new SimpleModule(); 完美运行。
                  • 对于 SpringBoot 版本 1.5.3.RELEASE 不需要添加 jackson-datatype-jsr310 依赖项。
                  【解决方案15】:

                  1) 依赖

                   compile group: 'com.fasterxml.jackson.datatype', name: 'jackson-datatype-jsr310', version: '2.8.8' 
                  

                  2) 日期时间格式的注解。

                  public class RestObject {
                  
                      private LocalDateTime timestamp;
                  
                      @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
                      public LocalDateTime getTimestamp() {
                          return timestamp;
                      }
                  }
                  

                  3) 弹簧配置。

                  @Configuration
                  public class JacksonConfig {
                  
                      @Bean
                      @Primary
                      public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) {
                          System.out.println("Config is starting.");
                          ObjectMapper objectMapper = builder.createXmlMapper(false).build();
                          objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
                          return objectMapper;
                      }
                  }
                  

                  【讨论】:

                  • 非常感谢。 @JsonFormat 是为我解决它的那个。由于某种原因,上述解决方案都不适合我
                  • ObjectWriter 是否有类似的配置,因为我需要将对象转换为字符串并将存储转换为 DB,但 LocalDateTime 文件以逗号分隔。
                  猜你喜欢
                  • 2019-05-19
                  • 2020-07-21
                  • 2016-03-31
                  • 2023-03-15
                  • 2021-11-26
                  • 1970-01-01
                  • 2018-02-12
                  • 2017-10-28
                  相关资源
                  最近更新 更多