1
votes

Given the following case class:

import java.time.LocalDate
case class ReportDateVO(reportDate: LocalDate)

I'm trying to define the implicit json format:

implicit val reportDatesWrite : Writes[ReportDateVO] = (
      (JsPath \ "dt").write[LocalDate]
  ) (unlift(ReportDateVO.unapply))

But I get the following error:

overloaded method value write with alternatives: (t: java.time.LocalDate)(implicit w: play.api.libs.json.Writes[java.time.LocalDate])play.api.libs.json.OWrites[play.api.libs.json.JsValue] (implicit w: play.api.libs.json.Writes[java.time.LocalDate])play.api.libs.json.OWrites[java.time.LocalDate] cannot be applied to (fdic.ReportDateVO ⇒ java.time.LocalDate)

What are these alternatives? there's no default format? how to fix this? I'm using Play 2.5.2.

2

2 Answers

1
votes

The short answer is you can only use JSON combinators for case classes with minimum number of parameters 2 (up to 22). Look at the docs for JSON Reads/Writes/Format Combinators, section Complex Reads. The combinators work similarly for Reads and Writes so short explanation in Complex Reads section might be helpful. So basically what compiler says to you is that you cannot pass function of type fdic.ReportDateVO ⇒ java.time.LocalDate to the method write what is kind of weird, because logically, if you have parentheses around the (JsPath \ "dt").write[LocalDate], which should return instance of OWrites[LocalDate], the compiler should complain about wrong apply method in object of type OWrites[LocalDate].

I think the best alternative (if you want to have custom filed name) is to implement Writes[LocalDate] manually.

implicit val reportDatesWrite: Writes[ReportDateVO] = OWrites[ReportDateVO] {
  rdvo: ReportDateVO => Json.obj(
    "dt" -> DefaultLocalDateWrites.writes(rdvo.reportDate)
  )
}

If field name can match the name of parameter in case class (reportDate) then you also can use Play helper method which is implemented using Scala macros.

implicit val reportDatesWrite: Writes[ReportDateVO] = Json.writes[ReportDateVO]
1
votes

PlayJson only provides serializers for basic types like Int, String, Double - LocalDate isn't one of them.

You have the right idea, but need to be more specific and define Combinator for LocalDate first:

   implicit val LocalDateWrites: Writes[LocalDate] = Writes {
        (l: LocalDate) => JsString(l.toString())
   }

    implicit val reportDatesWrite : Writes[ReportDateVO] = (
        (JsPath \ "dt").write[LocalDate]
    ) (unlift(ReportDateVO.unapply))