Search code examples
jsonscalaplayframework-2.0case-class

Play JSON Reads Error With Needed Implicits in Scope


I have a simple JSON reads and writes using the play json library:

  val dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
  implicit val jodaDateTimeReads: Reads[DateTime] = Reads[DateTime](js =>
    js.validate[String].map[DateTime](dt =>
      DateTime.parse(dt, DateTimeFormat.forPattern(dateFormat))
    )
  )

  implicit val jodaDateTimeWrites: Writes[DateTime] = new Writes[DateTime] {
    def writes(dt: DateTime): JsValue = JsString(dt.toString())
  }

I'm trying to use this DateTime to parse one of my case class which is

case class DefaultMessage(timestamp: DateTime)

I have the corresponding reads and writes in scope and the reads and writes for the DateTime is also in scope:

implicit val defaultMessageReads: Reads[DefaultMessage] = (
  (JsPath \ "timestamp").read[DateTime](jodaDateTimeReads)
)(DefaultMessage.apply _)

I get an error that says:

[error]  found   : org.joda.time.DateTime => com.my.project.messages.DefaultMessage
[error]  required: play.api.libs.json.Reads[?]
[error]         )(DefaultMessage.apply _)

What does this imply? I thought the signature for the Reads[DefaultMessage] satisfies with the implicit val defaultMessageReads. I can't see what is wrong with this snippet?


Solution

  • There you go.

    case class DefaultMessage(timestamp: DateTime)
    object DefaultMessage{
      val dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
      implicit val reads: Reads[DefaultMessage] =
        (json: JsValue) => (json \ "timestamp").validate[String]
          .map(t => DefaultMessage(DateTime.parse(t, DateTimeFormat.forPattern(dateFormat))))
    }
    

    You don't need to change your case class for that, although it makes more sense to have a message in a class called DefaultMessage:)