【问题标题】:Scala Play: how to define a "Json writable class"Scala Play:如何定义“Json 可写类”
【发布时间】:2016-12-06 12:35:30
【问题描述】:

我想写一个将case类转换为Json的函数:

import play.api.libs.json._

def myJson(cc: Product): JsValue = {
  Json.toJson(cc)  // simplified
}

每个案例类都有一个隐含的Writes[T],例如:

case class Test(a: Int)
object Test {
  implicit val jsonWrites: Writes[Test] = Json.writes[Test]
}

可以单独编写Json.toJson(new Test(1)),但上面的myJson 函数无法编译,因为它永远不知道cc 是否定义了隐式写入。

[如何编写函数签名以便它只接受具有Writes 隐式的类?]

编辑:如何编写函数输入类型,使其仅对应于具有Writes 隐式的类?

我试过了:

trait JsonWritableResult[T <: Product] {
  implicit val jsonWrites: Writes[T]
}

case class Test(a: Int)
object Test extends JsonWritableResult[Test] {
  implicit val jsonWrites: Writes[Test] = Json.writes[Test]
}

def myJson(cc: JsonWritableResult[_ <: Product]): JsValue = {
  Json.toJson(cc)
}

但它说“没有为类型 models.JsonWritableResult[_$2] 找到 Json 序列化程序”

【问题讨论】:

  • 为什么要自定义 myJson 函数用于任意案例类?和 Json.toJson 会有什么不同?
  • 只是因为我有 120 个这样的案例类,我不想编写 120 个控制器来返回那么多不同的 Json 结果。最好使用通用函数。
  • @Tyth 请注意,这可能确实很愚蠢,但我还没有意识到)
  • 您只需要在您的myJson 方法中接受(implicit writes: Writes[T])。这是什么意思 ?您要求编译器检查提供的类型是否具有 Writes 的实例
  • 如果我理解得很好,那就是Json.toJson已经有的签名。我真正需要的是一个特征/类型,我可以将它赋予工厂的所有结果,以便保证它们是toJson 的有效参数。看起来这个问题被问得很糟糕:(

标签: json scala playframework playframework-2.5


【解决方案1】:

这样的事情似乎给了你想要的行为。

import play.api.libs.json.{JsValue, Json, Writes}

trait Product {}

case class Test(a: Int) extends Product
object Test {
  implicit val jsonWrites: Writes[Test] = Json.writes[Test]
}

def myJson[T <: Product](cc: T)(implicit writes: Writes[T]): JsValue = {
  Json.toJson(cc)  // simplified
}

import Test._

myJson(Test(3))

这在一般情况下没有经过测试,但在工作表中似乎可以工作。

【讨论】:

    【解决方案2】:

    与其强制 case 类具有隐式,不如强制它从 trait 覆盖 toJson 方法,使用或不使用在 case 类中定义的隐式。简单得多,它的工作原理。然后我的工厂可以在其输出类型中显式此特征,因此我可以序列化它输出的任何内容。

    但由于另一个答案回答了我提出错误的问题,我接受它;)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-03-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多