Scala类型推迟

Joy*_*age 6 scala playframework-2.0

我正在使用Play framework 2.1和Scala 2.10.1,并希望构建一个通用函数来从自定义案例类的List中构造一个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!
    }
  }
Run Code Online (Sandbox Code Playgroud)

用法:

val applyJsonArray = buildJsArray(List[Apple])(new JsArray())
Run Code Online (Sandbox Code Playgroud)

但是,抛出了编译错误:

No Json deserializer found for type T. Try to implement an implicit Writes or Format for this 
 type.
Run Code Online (Sandbox Code Playgroud)

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

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

非常感谢!

sen*_*nia 15

如何修复错误

您必须向方法添加隐式参数,如下所示:

def buildJsArray[T](l: List[T])(result: JsArray)(implicit tjs: Writes[T]): JsArray
Run Code Online (Sandbox Code Playgroud)

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

你为什么要加这个参数的原因是,你知道如何转换Tjson只有当你知道什么T是.这意味着T只有在调用时才有序列化的方法,buildJsArray并且此参数允许您将此序列化方法传递给方法buildJsArray.

如何构建JSArray

你可以使用的构造函数JsArray.需要Seq[JsValue]:

new JsArray(l.map{Json.toJson(_)})
Run Code Online (Sandbox Code Playgroud)

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

加成

你应该看看集合api.它允许您编写更易读和更短的代码:

def buildJsArray[T](l: List[T])(implicit tjs: Writes[T]): JsArray =
  l.foldLeft(new JsArray){ (r, x) => r :+ Json.toJson(x) }
Run Code Online (Sandbox Code Playgroud)