In Play 2.3, I have a case class with a single optional double member:
case class SomeClass(foo: Option[Double])
I need a JSON write conver
Writes
isn't a covariant functor, so you can't use map
, but you can use contramap
:
import play.api.libs.json._
import play.api.libs.functional.syntax._
implicit val someClassWrites: Writes[SomeClass] =
(__ \ 'foo).writeNullable[Double].contramap(_.foo)
If you have more than one member, you can use Play's FunctionalBuilder
syntax:
case class AnotherClass(foo: Option[Double], bar: Option[String])
implicit val anotherClassWrites: Writes[AnotherClass] = (
(__ \ 'foo).writeNullable[Double] and
(__ \ 'bar).writeNullable[String]
)(ac => (ac.foo, ac.bar))
In the first case the argument to contramap
is just a function from the type you want a Writes
for to the type in the Writes
you're calling contramap
on. In the second case, the function at the end is from the target (AnotherClass
here) to a tuple of the Writes
instances you've built up with and
(in this case Option[Double]
and Option[String]
).
The easy way is:
import play.api.libs.json.Json
implicit val fmt = Json.format[SomeClass]
Which uses a macro to auto-generate the json format for you. Beats implementing writes directly.