scala play 2.1.1 json functional syntax mapping data to a different format
functional-programming, json, playframework, playframework-2.1, scala
Solution
I managed to get this one figured out, I was using the wrong type of functor map operations and had the types I was working with backwards. Here are working reads/writes implementations in the much nicer functional syntax.
implicit val writesBanner = (
(__ \ "id").write[Int] and
(__ \ "ownerId").write[Int] and
(__ \ "licenseeId").writeNullable[Int] and
(__ \ "statusColor").writeNullable[String] and
(__ \ "content").writeNullable[String] and
(__ \ "displayStart").write[String].contramap[DateTime](dt => userDateFormatter.print(dt)) and
(__ \ "displayEnd").write[String].contramap[DateTime](dt => userDateFormatter.print(dt)) and
(__ \ "created").write[DateTime] and
(__ \ "updated").write[DateTime]
)(unlift(Banner.unapply))
implicit val readsBanner = (
(__ \ "id").read[Int] and
(__ \ "ownerId").read[Int] and
(__ \ "licenseeId").readNullable[Int] and
(__ \ "statusColor").readNullable[String] and
(__ \ "content").readNullable[String] and
(__ \ "displayStart").read[String].fmap[DateTime](dt => DateTime.parse(dt, userDateFormatter)) and
(__ \ "displayEnd").read[String].fmap[DateTime](dt => DateTime.parse(dt, userDateFormatter)) and
(__ \ "created").read[DateTime] and
(__ \ "updated").read[DateTime]
)(Banner)
Problem
I'm trying to write a custom json serializer using the functional syntax and I can't seem to find the right way to solve this particular problem. I have a couple of joda DateTime objects that I want to write in a specific format for the UI consuming it. Can anyone show me where I've gone wrong? Here is the case class I am dealing with at the moment, nothing special going on. ``` case class Banner( id: Int = 0, ownerId: Int = 0, licenseeId: Option[Int] = None, statusColor: Option[String] = None, content: Option[String] = None, displayStart: DateTime = new DateTime(), displayEnd: DateTime = new DateTime(), created: DateTime = new DateTime(), updated: DateTime = new DateTime() ) ``` These are my imports for the serializer object. ``` import play.api.libs.json._ import play.api.libs.functional.syntax._ import org.joda.time.DateTime import org.joda.time.format.DateTimeFormat ``` First off, the joda DateTime converts to a long just fine implicitly so the macro expander works great if that's all I wanted. ``` object MySerializers { implicit val writesBanner = Json.writes[Banner] } ``` What I need is to convert the displayStart and displayEnd objects to a particular string format rather than the long value. This is what I tried to do. ``` object MySerializers { val userDateFormatter = DateTimeFormat.forPattern("MM/dd/yyyy HH:mm a") implicit val writesBanner = ( (__ \ "id").write[Int] and (__ \ "ownerId").write[Int] and (__ \ "licenseeId").write[Int] and (__ \ "statusColor").writeNullable[String] and (__ \ "content").writeNullable[String] and (__ \ "displayStart").write[DateTime].inmap[String](dt => userDateFormatter.print(dt)) and (__ \ "displayEnd").write[DateTime].inmap[String](dt => userDateFormatter.print(dt)) and (__ \ "created").write[DateTime] and (__ \ "updated").write[DateTime] )(unlift(Banner.unapply)) } ``` But the compiler is not happy about that, so I don't seem to understand the correct way to use the inmap function. ``` could not find implicit value for parameter fu: play.api.libs.functional.InvariantFunctor[play.api.libs.json.OWrites] [error] (__ \ "displayStart").write[DateTime].inmap[String](dt => userDateFormatter.print(dt)) and [error] ^ ``` Any advice is much appreciated.