小编典典

如何使用Jackson和java.time解析不同的ISO日期/时间格式?

spring-boot

我们的Rest API从多个外部参与者获取JSON输入。它们都使用“ ISO-ish”格式,但是时区偏移量的格式略有不同。这些是我们看到的一些最常见的格式:

2018-01-01T15:56:31.410Z
2018-01-01T15:56:31.41Z
2018-01-01T15:56:31Z
2018-01-01T15:56:31+00:00
2018-01-01T15:56:31+0000
2018-01-01T15:56:31+00

我们的堆栈是带有Jackson Jackson的Spring Boot
2.0。在我们的数据类中,我们经常使用类型java.time.OffsetDateTime

一些开发人员已尝试实现一种解析上述所有格式的解决方案,但都没有成功。特别是带有冒号(00:00)的第四个变体似乎无法解析。

如果该解决方案无需在模型的每个日期/时间字段上都添加注释,那将是很好的选择。

尊敬的社区,您有解决方案吗?


阅读 426

收藏
2020-05-30

共1个答案

小编典典

非常感谢您的所有投入!

我选择了jeedas建议的解串器和Ole VV建议的格式化器(因为它更短)。

class DefensiveIsoOffsetDateTimeDeserializer : JsonDeserializer<OffsetDateTime>() {
    private val formatter = DateTimeFormatterBuilder()
        .append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
        .appendPattern("[XXX][XX][X]")
        .toFormatter()

    override fun deserialize(p: JsonParser, ctxt: DeserializationContext) 
      = OffsetDateTime.parse(p.text, formatter)

    override fun handledType() = OffsetDateTime::class.java
}

我还添加了一个自定义序列化程序,以确保在生成json时我们使用正确的格式:

class OffsetDateTimeSerializer: JsonSerializer<OffsetDateTime>() {
    override fun serialize(
        value: OffsetDateTime, 
        gen: JsonGenerator, 
        serializers: SerializerProvider
    ) = gen.writeString(value.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME))

    override fun handledType() = OffsetDateTime::class.java
}

将所有部分放在一起,我@Configuraton在spring类路径中添加了一个类,以使其在数据类上没有任何注释地工作:

@Configuration
open class JacksonConfig {

  @Bean
  open fun jacksonCustomizer() = Jackson2ObjectMapperBuilderCustomizer { 
    it.deserializers(DefensiveIsoOffsetDateTimeDeserializer())
    it.serializers(OffsetDateTimeSerializer())
  }
}
2020-05-30