2

我有点困惑为什么下面的代码不起作用:

  implicit val connectReads: Reads[ConnectCommand] = (
    (JsPath \ "uuid").read[String]
    )(ConnectCommand.apply _)

  private def generateMessage[T](json: JsValue) = json.validate[T] match {
    case s: JsSuccess[T] => s.asOpt
    case e: JsError => None
  }

该函数将按如下方式调用:

generateMessage[ConnectCommand](json)

我收到以下错误:

Error:(59, 64) No Json deserializer found for type T. Try to implement an implicit Reads or Format for this type.
  private def generateMessage[T](json: JsValue) = json.validate[T] match {
                                                               ^
Error:(59, 64) not enough arguments for method validate: (implicit rds: play.api.libs.json.Reads[T])play.api.libs.json.JsResult[T].
Unspecified value parameter rds.
  private def generateMessage[T](json: JsValue) = json.validate[T] match {
                                                           ^

我对 Scala 泛型相当陌生......有什么办法可以做我想做的事情吗?

4

2 回答 2

3

根据文档,您的类型JsValue.validate需要一个隐式Reads可用:

def validate[T](implicit rds: Reads[T]): JsResult[T] 

假设您在拨打电话的地方可以使用它generateMessage,则必须将其传递给generateMessage,这样也validate可以看到它:

private def generateMessage[T](json: JsValue)(implicit rds: Reads[T])

或更短的形式:

private def generateMessage[T : Reads](json: JsValue)
于 2015-06-11T00:35:54.050 回答
1

这与泛型并没有真正的关系,而是隐式以及库如何要求您定义隐式类型并导入它们。

这是必需的,因为该validate功能不知道您的格式JsValue,因此需要implicit scope提供一个。然后它使用格式来验证它。起初它令人困惑,但最终会更好,因为当需要 JSON 格式时,您不必为每个方法调用显式提供格式。

这些也是在错误消息中给出它的两行:

Try to implement an implicit Reads or Format for this type.

not enough arguments for method validate: (implicit rds: play.api.libs.json.Reads[T])

我们看到您要么需要导入隐式Format/Reads要么自己定义一个。您可以在 Play 的相关部分了解如何执行此操作!文档

编辑:

您的方法缺少将(implicit reads: Reads[T])其传递给validate函数的隐式参数:

private def generateMessage[T](json: JsValue)(implicit reads: Reads[T]) = json.validate[T] match {
 case s: JsSuccess[T] => s.asOpt
 case e: JsError => None
}
于 2015-06-11T00:32:32.847 回答