【问题标题】:How to write a Play JSON writes converter for a case class with a single nullable member如何为具有单个可为空成员的案例类编写 Play JSON 写入转换器
【发布时间】:2014-12-14 22:45:22
【问题描述】:

在 Play 2.3 中,我有一个带有单个可选双精度成员的案例类:

case class SomeClass(foo: Option[Double])

我需要一个 JSON 写入转换器来处理可以为空的成员:

implicit val someClassWrite: Writes[SomeClass] = ???

Play docs provide an example

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

但遗憾的是,我无法弄清楚如何为 1) 单个可空值和 2) 双精度执行此操作。有任何想法吗?谢谢。

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

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

更新 #2: 忽略我的解决方案。特拉维斯布朗就是其中之一。

【问题讨论】:

  • 所有 play docs 示例所做的就是将 String 转换为 JsString,在 JSON 中没有 Option[Double] 的类比。您能否提供更多背景信息?
  • @LimbSoup 查看相同的文档:case class DisplayName(name:String) val nameReads: Reads[DisplayName] = (JsPath \ "name").read[String].map(DisplayName(_))。通过使用 .readNullable[Double] 代替,这对于读取转换器非常有效。我正在寻找等效的写入转换器。
  • writeNullable[Double] ??
  • @LimbSoup 我希望...value map is not a member of play.api.libs.json.OWrites[Option[Double]]
  • 你想映射什么?就像我说的,需要更多的上下文..

标签: scala playframework scala-2.10 playframework-2.3


【解决方案1】:

Writes 不是协变函子,所以不能使用map,但可以使用contramap

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

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

如果您有多个成员,则可以使用 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))

在第一种情况下,contramap 的参数只是一个函数,从您想要 Writes 的类型到您正在调用 contramapWrites 中的类型。在第二种情况下,最后的函数是从目标(此处为AnotherClass)到您使用and 构建的Writes 实例的元组(在本例中为Option[Double]Option[String]) .

【讨论】:

  • 这是否记录在任何地方?我找不到它,并且一直在为此奋斗,超出了必要的范围,哈哈。反映射位是
【解决方案2】:

简单的方法是:

import play.api.libs.json.Json

implicit val fmt = Json.format[SomeClass]

它使用宏为您自动生成 json 格式。优于直接实现写入。

【讨论】:

  • 我应该补充一点,它是一个复杂的写入系统的一部分......递归写入等。有困难的方法吗?
  • 如果您的案例类的属性是 someId:String 并且包含您的 someId 的 JSON 元素是“some-ID”,那么您不能使用宏生成的格式。
猜你喜欢
  • 1970-01-01
  • 2017-08-23
  • 1970-01-01
  • 2014-02-17
  • 1970-01-01
  • 1970-01-01
  • 2018-10-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多