【问题标题】:scala json4s, can't convert LocalDatescala json4s,无法转换 LocalDate
【发布时间】:2016-01-27 14:20:16
【问题描述】:

我遇到了 org.json4s (scala)、joda.time.LocalDate 和 org.json4s.ext.JodaTimeSerializers 的问题。鉴于 JodaTimeSerializers.all 中有一个 LocalDate 转换,我希望我可以执行以下操作,但我得到了之后显示的异常

scala> import org.json4s.JString
import org.json4s.JString

scala> import org.joda.time.LocalDate
import org.joda.time.LocalDate

scala> import org.json4s.ext.JodaTimeSerializers
import org.json4s.ext.JodaTimeSerializers

scala> import org.json4s._
import org.json4s._

scala> implicit val formats: Formats = DefaultFormats ++ JodaTimeSerializers.all
formats: org.json4s.Formats = org.json4s.Formats$$anon$3@693d3d7f

scala> val jDate = JString("2016-01-26")
jDate: org.json4s.JsonAST.JString = JString(2016-01-26)

scala> jDate.extract[LocalDate]
org.json4s.package$MappingException: Can't convert JString(2016-01-26) to class org.joda.time.LocalDate

另一方面,这行得通(不足为奇)

scala> val jodaDate = LocalDate.parse(jDate.values)

我尝试创建一个自定义的序列化器,它永远不会被称为 b/c,它似乎属于 JodaSerializer 领域。我还创建了一个自定义反序列化器,它将与 Java.time.LocalDate (字符串中的 int 和字节)一起使用,但 java.time.LocalDate 与其他一些代码混淆,这可能是一个不同的问题......这个是:我我通过 JodaTimeSerializers.all 寻找线索无法解析 JString(2016-01-26) 或任何日期字符串。

异常顶部为:org.json4s.package$MappingException:

Can't convert JString(2016-01-01) to class org.joda.time.LocalDate (JodaTimeSerializers.scala:126)

编辑 这仍然在咬我,所以再挖一点,它可以用以下方法重现。

import org.joda.time.LocalDate
import org.json4s.ext.JodaTimeSerializers
import org.json4s._
implicit val formats: Formats = DefaultFormats ++ JodaTimeSerializers.all
import org.joda.time.LocalDate
case class MyDate(myDate: LocalDate)
val stringyDate =
"""
{
  "myDate" : "2016-01-01"
}
"""
import org.json4s.jackson.JsonMethods.parse
parse(stringyDate).extract[MyDate]

org.json4s.package$MappingException: No usable value for myDate
Can't convert JString(2016-01-01) to class org.joda.time.LocalDate

这似乎发生在 JodaTimeSerializers.scala 的第 125 行,它不是 JObject,而是 JString,因此它属于第 126 行的值情况,这会引发错误。

在这里添加它以防它咬到其他人并希望得到一些帮助来修复它......但现在我迟到了。我已将代码移至本地,希望明天能解决。

【问题讨论】:

  • 我已经在 scalatra 方面解决了这个问题,但现在 play 无法反序列化它 b/c 它作为 {year: 2016, month: 03: day 的子对象出现09} 而不仅仅是一个简单的日期。
  • 您需要双方就通用格式达成一致。所以要么教play如何读取日期对象,要么通过编写自定义Serializer[LocalDate]而不是使用JodaTimeSerializer.all来教对方play的日期格式。
  • 注意:Json4s 是 vulnerable under DoS/DoW attacks!

标签: scala jodatime json4s


【解决方案1】:

这行得通。我为LocalDate 定义了一个自定义序列化程序。

import org.json4s.JString
import org.joda.time.LocalDate
import org.json4s._

case object LocalDateSerializer
    extends CustomSerializer[LocalDate](
      format =>
        ({
          case JString(s) => LocalDate.parse(s)
        }, Map() /* TO BE IMPLEMENTED */)
    )

implicit val formats: Formats = DefaultFormats + LocalDateSerializer
val jDate = JString("2016-01-26")
jDate.extract[LocalDate] // res173: org.joda.time.LocalDate = 2016-01-26

【讨论】:

【解决方案2】:

新的序列化程序包含在库中,但不是默认格式:

implicit val formats: Formats = DefaultFormats ++ JavaTimeSerializers.all

【讨论】:

  • 不幸的是,尽管JavaTimeSerializers 中的LocalDate 序列化程序无法处理单个日期字符串。它序列化并期望具有字段daymonthyear 的对象。这不是很有帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-18
  • 2019-09-17
  • 2020-07-05
  • 2019-07-22
相关资源
最近更新 更多