6

我正在使用 Play framework 2.1 和 Scala 2.10.1,并且想构建一个通用函数来从自定义案例类列表中构造一个 JsArray。

private def buildJsArray[T](l: List[T])(result: JsArray): JsArray = {
    l match {
      case List() => result
      case x::xs => buildJsArray(xs)(result :+ Json.toJson(x)) // compiling error here!
    }
  }

用法:

val applyJsonArray = buildJsArray(List[Apple])(new JsArray())

但是,会引发编译错误:

No Json deserializer found for type T. Try to implement an implicit Writes or Format for this 
 type.

我确实有一个为特定案例类(即 Apple 案例类)编写的 Json 反序列化器。

如何推迟编译器在运行时而不是在编译时检查 x 的类型?

非常感谢!

4

1 回答 1

15

如何修复错误

您必须像这样向您的方法添加一个隐式参数

def buildJsArray[T](l: List[T])(result: JsArray)(implicit tjs: Writes[T]): JsArray

方法中有这样的参数Json.toJson

之所以要加这个参数,是因为只有知道是什么才T知道怎么转换。这意味着您只有在调用时才有序列化方法,并且此参数允许您将此序列化方法传递给方法。jsonTTbuildJsArraybuildJsArray

如何构建一个 JSArray

您可以只使用JsArray. 它需要一个Seq[JsValue]

new JsArray(l.map{Json.toJson(_)})

已经有一个隐含Writes的 forTraversable所以你不需要自己的方法buildJsArray,你可以只使用Json.toJson带有 type 参数的方法List[T]

添加

你应该看看 collections api。它允许您编写更具可读性和更短的代码:

def buildJsArray[T](l: List[T])(implicit tjs: Writes[T]): JsArray =
  l.foldLeft(new JsArray){ (r, x) => r :+ Json.toJson(x) }
于 2013-06-25T05:41:29.200 回答