0

当我在 Playframework 中进行隐式 JSON 调用时,Tuple-2 起作用:

def toJson(itemTuple: List[((Item, ItemOption), List[Picture])]) : JsObject = { ... }

我定义了一个隐式 Writes 方法,一切都很好。在这种情况下,我可以在“外部”JSON 块中传递这样的列表:

"items" -> Json.toJson(itemTupleList)

并且在每个元素上执行隐式方法“toJson”。但是,当我将它扩展到 Tuple-3 时,它失败了:

def toJson(itemTuple: List[((Item, ItemOption, ItemAttribute), List[Picture])]) : JsObject = { ... }

这产生:

sbt.PlayExceptions$CompilationException: Compilation error[No Json deserializer found for type List[(models.butik.Item, models.butik.ItemOption, models.butik.ItemAttribute)]. Try to implement an implicit Writes or Format for this type.]

我以为我做到了:

implicit val iW = new Writes[((Item, ItemOption, ItemAttribute), List[Picture])] { ... }

这是什么原因?是否有另一种方法可以在没有隐式方法的情况下实现相同的效果(我对 Scala 有点陌生)。

(顺便说一句:将 Item 数据拆分为三个容器的原因是由于 Slick 依赖的 Scala 的 22 个元组元素。)

4

1 回答 1

1

这对我有用:

import play.api.libs.json._

object Scratch {

  def main(args: Array[String]): Unit = {
    println(toJson(List(((1, 2, 3), List(3)))))
  }

  def toJson(itemTuple: List[((Item, ItemOption, ItemAttribute), List[Picture])]) : JsValue =
    Json.toJson(itemTuple)

  implicit val iW: Writes[((Item, ItemOption, ItemAttribute), List[Picture])] = new Writes[((Item, ItemOption, ItemAttribute), List[Picture])] {
    def writes(x: ((Item, ItemOption, ItemAttribute), List[Picture])) = Json.parse("[1, 2, 3, [3]]") // TODO
  }

  type Item = Int
  type ItemOption = Int
  type ItemAttribute = Int
  type Picture = Int
}

.

% cat build.sbt
scalaVersion := "2.10.2"

libraryDependencies ++= Seq(
  "com.typesafe.play" %% "play-json" % "2.2.0-RC2"
)

resolvers += "Typesafe Repository" at "http://repo.typesafe.com/typesafe/releases/"

% sbt run
[info] Loading project definition from /Users/jason/code/scratch4/project
[info] Set current project to scratch4 (in build file:/Users/jason/code/scratch4/)
[info] Running scratch.Scratch
[[1,2,3,[3]]]
[success] Total time: 0 s, completed Sep 26, 2013 1:16:21 PM

确保注释隐式的返回类型,而不是使用推断类型。如果隐式出现在你需要的地方下面并且返回类型不是显式的,编译器不会考虑。如果是这样,类型推断可能会陷入令人讨厌的循环。

顺便说一句,您可以使用类型别名稍微清理代码:

 def toJson(itemTuple: List[Record]): JsValue =
    Json.toJson(itemTuple)

  implicit def recordWrite: Writes[Record] = new Writes[Record] {
    def writes(rec: Record) = {
      Json.parse("{}") // TODO
    }
  }

  type Record = ((Item, ItemOption, ItemAttribute), List[Picture])
  type Item = Int
  type ItemOption = Int
  type ItemAttribute = Int
  type Picture = Int
}
于 2013-09-26T11:13:11.423 回答