在春季使用 JSR310 java.time 时将日期、即时序列化为 ISO 8601

Posted

技术标签:

【中文标题】在春季使用 JSR310 java.time 时将日期、即时序列化为 ISO 8601【英文标题】:Serialize Date, Instant to ISO 8601 when using JSR310 java.time in spring 【发布时间】:2017-04-26 14:52:13 【问题描述】:

我正在用 JSR310 替换 JodaTime,并且 JodaTime() 的模块工作正常。

我正在尝试在我的 spring-boot 应用程序中重新配置日期的序列化。

我不能同时保留两者,所以我正在寻找一种方法来将我的日期序列化/反序列化为 ISO 8601。

我遵循了这里的建议,但这并没有帮助: http://lewandowski.io/2016/02/formatting-java-time-with-spring-boot-using-json/

这是我的JacksonConfig.javaobjectMapper

@Configuration
public class JacksonConfig extends RepositoryRestMvcConfiguration 

    private static final Logger logger = LoggerFactory.getLogger(JacksonConfig.class);
    public static final DateTimeFormatter FORMATTER = ofPattern("dd::MM::yyyy");

    @Bean
    // Override and Primary due to bug: https://github.com/spring-projects/spring-boot/issues/6529
    @Override
    @Primary
    public ObjectMapper objectMapper() 
        ObjectMapper mapper = new ObjectMapper();
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        mapper.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, true);
        mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        JavaTimeModule javaTimeModule = new JavaTimeModule();
        javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer());
        javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer());
        mapper.registerModule(javaTimeModule);
        return mapper;
    

    public class LocalDateSerializer extends JsonSerializer<LocalDate> 
        @Override
        public void serialize(LocalDate value, JsonGenerator gen, SerializerProvider serializers) throws IOException 
            gen.writeString(value.format(FORMATTER));
        
    
    public class LocalDateDeserializer extends JsonDeserializer<LocalDate> 
        @Override
        public LocalDate deserialize(JsonParser p, DeserializationContext ctx) throws IOException 
            return LocalDate.parse(p.getValueAsString(), FORMATTER);
        
    

bean 被实例化,但 serializedeserialize 从未被调用。

我也试过没有自定义序列化器/反序列化器的JavaTimeModule,它也不起作用。

好像一点效果都没有。

有没有办法再调试一下?

我正在使用 spring-hateoas 和 spring-data,我遇到了可能相关的问题:

https://github.com/spring-projects/spring-hateoas/issues/333

【问题讨论】:

【参考方案1】:

利用 java time 模块中提供的 ser/deser。这实际上使用自定义格式化程序设置它们。

import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;

public ObjectMapper objectMapper() 
    ObjectMapper mapper = new ObjectMapper();
    mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    mapper.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, true);
    mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
    JavaTimeModule javaTimeModule = new JavaTimeModule();
    LocalDateSerializer localDateSerializer = new LocalDateSerializer(FORMATTER);
    javaTimeModule.addSerializer(LocalDate.class, localDateSerializer);
    LocalDateDeserializer localDateDeserializer = new LocalDateDeserializer(FORMATTER);
    javaTimeModule.addDeserializer(LocalDate.class, localDateDeserializer);
    mapper.registerModule(javaTimeModule);
    return mapper;

【讨论】:

你知道为什么这没有任何效果,怎么可能。我调试这个?正如我所说,反序列化器序列化永远不会被解雇 如何将它们直接添加到对象映射器中?我不明白,对不起 你可以在不注册java时间模块的情况下尝试。使用简单模块添加 ser/deser 并在对象映射器中注册模块。SimpleModule module = new SimpleModule(); module.addSerializer(LocalDate.class, new LocalDateSerializer()); mapper.registerModule(模块);像这样的东西。 使用 SimpleModule 代替 JavaTimeModule 不起作用,它没有改变任何东西,序列化被忽略。 不知道为什么我被否决了,但为清楚起见添加了 jsr310 ser/deser 的导入。

以上是关于在春季使用 JSR310 java.time 时将日期、即时序列化为 ISO 8601的主要内容,如果未能解决你的问题,请参考以下文章

如何正确地在Spring Data JPA和Jackson中用上Java 8的时间相关API(即JSR 310也即java.time包下的众神器)

javax 与 java 包

springboot Thymeleaf中格式化jsr310新日期时间类(LocalDateTime,LocalDate)

如何使用 Spring Data JPA 持久化 JSR-310 类型?

在 Java 8 / jsr310 中格式化持续时间

如何使用 jsr310 DateTimeFormatter 解析不区分大小写的字符串?