4

我无法将 org.joda.time.DateTime 字段从 JSON 反序列化为案例类。

JSON:
val ajson=parse(""" { "creationDate": "2013-01-02T10:48:41.000-05:00" }""")

我还设置了这些序列化选项:
implicit val formats = Serialization.formats(NoTypeHints) ++ net.liftweb.json.ext.JodaTimeSerializers.all

和反序列化:
val val1=ajson.extract[Post]

Post 是:
case class Post(creationDate: DateTime){ ... }

我得到的例外是:

 net.liftweb.json.MappingException: No usable value for creationDate
    Invalid date format 2013-01-02T10:48:41.000-05:00

如何将该日期字符串反序列化为 DateTime 对象?

编辑:
这有效:val date3= new DateTime("2013-01-05T06:24:53.000-05:00") 它使用与反序列化中的 JSON 相同的日期字符串。这里发生了什么事?

4

2 回答 2

9

似乎这是DateParserLift 默认使用的格式。在深入研究代码时,您可以看到解析器DateParser.parse(s, format)在将结果传递给构造函数之前尝试使用org.joda.time.DateTime.

object DateParser {
  def parse(s: String, format: Formats) = 
    format.dateFormat.parse(s).map(_.getTime).getOrElse(throw new MappingException("Invalid date format " + s))
}

case object DateTimeSerializer extends CustomSerializer[DateTime](format => (
  {
    case JString(s) => new DateTime(DateParser.parse(s, format))
    case JNull => null
  },
  {
    case d: DateTime => JString(format.dateFormat.format(d.toDate))
  }
))

Lift 似乎使用的格式是:yyyy-MM-dd'T'HH:mm:ss.SSS'Z'

为了解决这个问题,您可以指定正确的模式并将其添加到您的序列化选项中,或者如果您希望让 JodaTime 构造函数完成所有工作,您可以创建自己的序列化程序,例如:

case object MyDateTimeSerializer extends CustomSerializer[DateTime](format => (
  {
    case JString(s) => tryo(new DateTime(s)).openOr(throw new MappingException("Invalid date format " + s))
    case JNull => null
  },
  {
    case d: DateTime => JString(format.dateFormat.format(d.toDate))
  }
))

然后将其添加到您的格式列表中,而不是net.liftweb.json.ext.JodaTimeSerializers.all

于 2013-04-14T07:57:27.990 回答
0

可能不是 100% 优雅,但只有几行,可读性强且有效:

val SourISODateTimeFormat = DateTimeFormat.forPattern("YYYY-MM-dd'T'HH:mm:ss.SSSZ")
val IntermediateDateTimeFormat = DateTimeFormat.forPattern("YYYY-MM-dd'T'HH:mm:ss'Z'")

def transformTimestamps(jvalue: JValue) = jvalue.transform {
  case JField(name @ ("createdTime" | "updatedTime"), JString(value)) =>
    val dt = SourceISODateTimeFormat.parseOption(value).get
    JField(name, JString(IntermediateDateTimeFormat.print(dt)))
}
于 2014-03-31T08:55:46.723 回答