You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Scala Case Class使用Jackson JsonFormat序列化日期失效问题

解决Scala Case Class中Joda DateTime的@JsonFormat注解失效问题

问题分析

你遇到的问题是Jackson序列化Joda DateTime时,未应用@JsonFormat指定的格式,反而输出了完整的对象结构。核心原因是未在ObjectMapper中注册JodaModule——虽然已引入jackson-datatype-joda依赖,但该模块不会自动生效,必须显式添加到ObjectMapper中,否则Jackson无法识别Joda时间类型的序列化规则,只能用默认的对象序列化逻辑。

解决方案

1. 修正ObjectMapper配置

创建ObjectMapper时必须注册JodaModule,同时保留Scala模块的注册,调整后的序列化代码如下:

val mapper = new ObjectMapper() with ScalaObjectMapper
// 注册Joda模块与Scala模块(顺序不影响,但两者必须同时存在)
mapper.registerModule(new JodaModule())
mapper.registerModule(DefaultScalaModule)
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
// 可选:全局设置时区,避免格式中的时区偏移不一致
mapper.setTimeZone(TimeZone.getTimeZone("UTC"))

val inputJson = new StringReader(mapper.writeValueAsString(sampleCaseClass))

2. 优化Case Class注解(可选)

你的Case Class注解已基本正确,可补充时区参数避免默认时区导致的格式差异:

import com.fasterxml.jackson.annotation.{JsonProperty, JsonFormat}
import org.joda.time.DateTime

case class SampleCaseClass(
    @JsonProperty("a") 
    @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZ", timezone = "UTC") // 显式指定时区
    a: DateTime,
    @JsonProperty("b_id") b: String,
    @JsonProperty("c_id") c: String
)

3. Spring Boot全局配置(适配你的环境)

在Spring Boot 2.7.6项目中,可通过配置类统一配置Jackson,避免手动重复创建ObjectMapper:

import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.scala.DefaultScalaModule
import com.fasterxml.jackson.datatype.joda.JodaModule
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

@Configuration
class JacksonConfig {
    @Bean
    def objectMapper(): ObjectMapper = {
        val mapper = new ObjectMapper()
        mapper.registerModule(new JodaModule())
        mapper.registerModule(DefaultScalaModule)
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
        mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
        mapper.setTimeZone(java.util.TimeZone.getTimeZone("UTC"))
        mapper
    }
}

验证效果

修改后序列化SampleCaseClass实例,日期字段会输出指定格式的字符串,示例如下:

{"a":"1970-01-01T00:00:00.010+0000","b_id":"abc","c_id":"efg"}

反序列化也会自动识别该格式字符串并转换为Joda DateTime对象,完全适配Elasticsearch 7.17的字段要求。

内容的提问来源于stack exchange,提问作者nutim

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 23:12:24