Spring Boot 中的 JSON Java 8 LocalDateTime 格式

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/29956175/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 08:52:54  来源:igfitidea点击:

JSON Java 8 LocalDateTime format in Spring Boot

javajsonjava-8spring-bootjava-time

提问by Erik Pragt

I'm having a small problem with formatting a Java 8 LocalDateTime in my Spring Boot Application. With 'normal' dates I have no problem, but the LocalDateTime fields are converted to the following:

我在 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"
    }
  }

While I would like convert it to something like:

虽然我想将其转换为以下内容:

"startDate": "2015-01-01"

My code looks like this:

我的代码如下所示:

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

But either of the above annotations don't work, the date keeps getting formatted like above. Suggestions welcome!

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

采纳答案by Erik Pragt

update: Spring Boot 2.x doesn't require this configuration anymore. I've written a more up to date answer here.

更新:Spring Boot 2.x 不再需要此配置。我在这里写了一个更新的答案



(This is the way of doing it before Spring Boot 2.x, it might be useful for people working on an older version of Spring Boot)

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

I finally found herehow to do it. To fix it, I needed another dependency:

我终于在这里找到怎么做。为了修复它,我需要另一个依赖项:

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

By including this dependency, Spring will automatically register a converter for it, as described here. After that, you need to add the following to application.properties:

通过包括这种依赖关系,Spring会自动注册一个转换器,它作为描述在这里。之后,您需要在 application.properties 中添加以下内容:

spring.Hymanson.serialization.write_dates_as_timestamps=false

This will ensure that a correct converter is used, and dates will be printed in the format of 2016-03-16T13:56:39.492

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

Annotations are only needed in case you want to change the date format.

仅当您想更改日期格式时才需要注释。

回答by patelb

I added the com.fasterxml.Hymanson.datatype:Hymanson-datatype-jsr310:2.6.1dependency and i started to get the date in the following format:

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

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

which is not what i wanted but i was getting closer. I then added the following

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

spring.Hymanson.serialization.write_dates_as_timestamps=false

to application.properties file which gave me the correct format that i needed.

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

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

回答by Matt Broekhuis

Here it is in maven, with the property so you can survive between spring boot upgrades

这是在 maven 中的属性,因此您可以在弹簧靴升级之间生存

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

回答by Yan Khonski

1) Dependency

1) 依赖

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

2) Annotation with date-time format.

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

public class RestObject {

    private LocalDateTime timestamp;

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

3) Spring Config.

3) 弹簧配置。

@Configuration
public class HymansonConfig {

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

回答by Ida Amit

I found another solution which you can convert it to whatever format you want and apply to all LocalDateTime datatype and you do not have to specify @JsonFormat above every LocalDateTime datatype. first add the dependency :

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

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

Add the following 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 Hymanson2ObjectMapperBuilder will allow you to customize both default ObjectMapper and XmlMapper (used in MappingHymanson2HttpMessageConverter and MappingHymanson2XmlHttpMessageConverter 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;
    }
}

in your config file add the following :

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

@Import(Java8DateTimeConfiguration.class)

This will serialize and de-serialize all properties LocalDateTime and ZonedDateTime as long as you are using objectMapper created by spring.

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

The format that you got for ZonedDateTime is : "2017-12-27T08:55:17.317+02:00[Asia/Jerusalem]" for LocalDateTime is : "2017-12-27T09:05:30.523"

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

回答by Manuel Antonio

This work fine:

这项工作很好:

Add the dependency:

添加依赖:

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

Add the annotation:

添加注释:

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

Now, you must get the correct format.

现在,您必须获得正确的格式。

To use object mapper, you need register the JavaTime

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

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

回答by Ram

@JsonDeserialize(using= LocalDateDeserializer.class)does not work for me with the below dependency.

@JsonDeserialize(using= LocalDateDeserializer.class)以下依赖项对我不起作用。

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

I have used the below code converter to deserialize the date into a java.sql.Date.

我使用以下代码转换器将日期反序列化为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();
    }
}

回答by JWiryo

Writing this answer as a reminder for me as well.

写这个答案也是对我的提醒。

I combined several answers here and in the end mine worked with something like these. (I am using SpringBoot 1.5.7 and Lombok 1.16.16)

我在这里结合了几个答案,最后我使用了类似的方法。(我使用的是 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;

}

回答by yuranos

As already mentioned, spring-boot will fetch all you need (for both web and webflux starter).

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

But what's even better - you don't need to register any modules yourself. Take a look here. Since @SpringBootApplicationuses @EnableAutoConfigurationunder the hood, it means HymansonAutoConfigurationwill be added to the context automatically. Now, if you look inside HymansonAutoConfiguration, you will see:

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

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

This fellawill be called in the process of initialization and will fetch all the modules it can find in the classpath. (I use Spring Boot 2.1)

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

回答by Kalpesh Soni

I am using Springboot 2.0.6 and for some reason, the app yml changes did not work. And also I had more requirements.

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

I tried creating ObjectMapper and marking it as Primary but spring boot complained that I already have HymansonObjectMapper as marked Primary!!

我尝试创建 ObjectMapper 并将其标记为 Primary 但 spring boot 抱怨我已经将 HymansonObjectMapper 标记为 Primary !

So this is what I did. I made changes to the internal mapper.

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

My Serializer and Deserializer are special - they deal with 'dd/MM/YYYY'; and while de-serializing - it tries its best to use 3-4 popular format to make sure I have some LocalDate.

我的序列化器和反序列化器很特别——它们处理“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;
}