Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to deserialize DateTime in Lift

I am having trouble deserializing a org.joda.time.DateTime field from JSON into a case class.

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

I also set these serialization options:
implicit val formats = Serialization.formats(NoTypeHints) ++ net.liftweb.json.ext.JodaTimeSerializers.all

And the deserialization:
val val1=ajson.extract[Post]

where Post is:
case class Post(creationDate: DateTime){ ... }

The exception I get is:

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

How can I deserialize that date string into a DateTime object?

EDIT:
This works: val date3= new DateTime("2013-01-05T06:24:53.000-05:00") which uses the same date string from the JSON as in the deserialization. What's happening here?

like image 715
Adrian Avatar asked Jan 14 '23 16:01

Adrian


1 Answers

Seems like it is the DateParser format that Lift uses by default. In digging into the code, you can see that the parser attempts to use DateParser.parse(s, format) before passing the result to the constructor for 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))
  }
))

The format that Lift seems to be using is: yyyy-MM-dd'T'HH:mm:ss.SSS'Z'

To get around that, you could either specify the correct pattern and add that to your serialization options, or if you would prefer to just have the JodaTime constructor do all the work, you could create your own serializer like:

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))
  }
))

And then add that to your list of formats, instead of net.liftweb.json.ext.JodaTimeSerializers.all

like image 173
jcern Avatar answered Jan 16 '23 05:01

jcern