JodaTime序列化问题:升级json4s-core后时区日期转换报错
解决json4s-core 3.6.0-M3升级后JodaTime DateTime序列化报错问题
这个报错的核心原因是json4s 3.x系列对日期解析的返回类型做了变更:原来的DateParser.parse()直接返回Joda的DateTime,但在3.6.0-M3版本里,它返回的是json4s内部的DateParser.ZonedInstant类型,而你的自定义序列化器里没有处理这个类型到DateTime的转换,所以触发了No instant converter found的错误。
下面给你两种可行的解决办法:
方法一:手动将ZonedInstant转换为Joda DateTime
直接在你的回退逻辑里,把DateParser.parse()返回的ZonedInstant转换成Joda的DateTime,这样就能兼容新的返回类型了。调整后的代码片段如下:
case JString(s) => Try(format.dateTimeFormat.parseDateTime(s)) .getOrElse { val zonedInstant = DateParser.parse(s) // 根据ZonedInstant的时区和时间戳创建DateTime new DateTime(zonedInstant.toInstant, DateTimeZone.forID(zonedInstant.zone.id)) }
这里的关键是调用zonedInstant.toInstant()拿到时间戳,再用它的时区信息初始化Joda DateTime,保证日期和时区的准确性。
方法二:注册ZonedInstant到DateTime的转换器
如果你希望更通用地处理这个类型,可以在json4s的格式定义里添加一个专门的转换器,把ZonedInstant自动转成DateTime:
import org.json4s._ import org.json4s.ext.DateParser import org.joda.time.{DateTime, DateTimeZone} // 新增ZonedInstant到DateTime的转换器 val zonedInstantToDateTime = new CustomSerializer[DateTime](_ => ( { case JString(s) => val zonedInstant = DateParser.parse(s) new DateTime(zonedInstant.toInstant, DateTimeZone.forID(zonedInstant.zone.id)) }, { case _: DateTime => JNull } // 序列化逻辑不需要,这里只是占位 )) // 把转换器加入你的Formats implicit val jsonFormats: Formats = DefaultFormats ++ List(zonedInstantToDateTime, 你的自定义序列化器)
不过更推荐第一种方法,因为它直接修改你现有自定义序列化器的回退逻辑,代码改动最小,也更贴合你的业务场景。
另外要注意:如果你的应用不需要兼容旧版本的json4s,也可以考虑逐步迁移到Java 8+的java.time API,json4s对新的日期API支持更完善,后续版本也会更侧重这部分的维护。
内容的提问来源于stack exchange,提问作者stan
相关产品推荐
相关产品推荐

