you are right, of course. I need only to sort my events in
chronological order, so the string representation is perhaps an
acceptable solution, but it would be much better to use ISODates.
Here is a modified version of my example which uses ISODates:
import play.api.libs.functional.syntax._
import play.api.libs.json.{JsNumber, JsObject, JsPath, JsSuccess, JsValue, Json, Reads, Writes}
import play.modules.reactivemongo.json.BSONFormats._
import reactivemongo.bson.BSONDateTime
implicit val dateTimeReads = new Reads[DateTime] {
def reads(jv: JsValue) = {
jv match {
case JsObject(Seq(("$date", JsNumber(millis)))) => JsSuccess(new DateTime(millis.toLong))
case _ => throw new Exception(s"Unknown JsValue for DateTime: $jv")
}
}
}
implicit val dateTimeWrites = new Writes[DateTime] {
def writes(dt: DateTime): JsValue = {
Json.toJson(BSONDateTime(dt.getMillis)) // {"$date": millis}
val externalDateTimeReads = play.api.libs.json.Reads.jodaDateReads(dateTimePattern)
val externalDateTimeWrites = play.api.libs.json.Writes.jodaDateWrites(dateTimePattern)
val externalEventWrites: Writes[Event] = (
(JsPath \ "eventID").writeNullable[UUID] and
(JsPath \ "userID").writeNullable[UUID] and
(JsPath \ "title").write[String] and
(JsPath \ "description").write[String] and
(JsPath \ "startDate").write[DateTime](externalDateTimeWrites) and
(JsPath \ "endDate").write[DateTime](externalDateTimeWrites) and
(JsPath \ "allDay").write[Boolean]
)(unlift(Event.unapply))
val externalEventRead: Reads[Event] = (
(JsPath \ "eventID").readNullable[UUID] Ande
(JsPath \ "userID").readNullable[UUID] and
(JsPath \ "title").read[String] and
(JsPath \ "description").read[String] and
(JsPath \ "startDate").read[DateTime](externalDateTimeReads) and
(JsPath \ "endDate").read[DateTime](externalDateTimeReads) and
(JsPath \ "allDay").read[Boolean]
)(Event.apply _)
}
The implicit Writes and Reads convert DateTime objects to/from
{"$date": millis}, which is stored as ISODate() in
Mongo. externalDateTimeWrites and externalDateTimeReads can be
esplicitly used when a more human-readable Json representation of an
Event is needed (e.g. to exchange Json data with clients).