如何为具有单个可空成员的案例类编写Play JSON写入转换器

Las*_*asf 9 scala playframework scala-2.10 playframework-2.3

在Play 2.3中,我有一个带有一个可选双成员的case类:

case class SomeClass(foo: Option[Double])
Run Code Online (Sandbox Code Playgroud)

我需要一个JSON写入转换器,将成员处理为可空:

implicit val someClassWrite: Writes[SomeClass] = ???
Run Code Online (Sandbox Code Playgroud)

播放文档提供了一个例子:

case class DisplayName(name:String)
implicit val displayNameWrite: Writes[DisplayName] = Writes {
  (displayName: DisplayName) => JsString(displayName.name)
}
Run Code Online (Sandbox Code Playgroud)

但遗憾的是我无法弄清楚如何做到这一点1)单个可空和2)双.有任何想法吗?谢谢.

更新#1:我能想出的唯一解决方案是:

implicit val someClassWrite: Writes[SomeClass] = Writes {
  (someClass: SomeClass) => someClass.foo match {
    case Some(f) => JsNumber(BigDecimal(f))
    case _ => JsNull
}
Run Code Online (Sandbox Code Playgroud)

更新#2:忽略我的解决方案.Travis Brown就是其中之一.

Tra*_*own 24

Writes不是协变仿函数,所以你不能使用map,但你可以使用contramap:

import play.api.libs.json._
import play.api.libs.functional.syntax._

implicit val someClassWrites: Writes[SomeClass] =
  (__ \ 'foo).writeNullable[Double].contramap(_.foo)
Run Code Online (Sandbox Code Playgroud)

如果您有多个成员,则可以使用Play的FunctionalBuilder语法:

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))
Run Code Online (Sandbox Code Playgroud)

在第一种情况下,参数to contramap只是一个函数,从你想要Writes的类型到Writes你正在调用的类型contramap.在第二种情况下,在最后的功能是从目标(AnotherClass在这里)的元组Writes,你已经建立了与实例and(在这种情况下,Option[Double]Option[String]).