5

我正在尝试使用 JSON 请求将数据从客户端发送到服务器。JSON 请求的正文如下所示:

{
"upload":
    {
    "ok":"some message",
    "assemblyId":"a9d8f72q3hrq982hf98q3"
    }
}

Play 能够将请求正文识别为 JSON,但是当我尝试解析单个值(即“上传”对象)时,Play 抱怨它找不到指定的参数。

Scala方法如下:

def add(course:Long) = withAccount { account => implicit request =>
  println()
  println(request.body)  // output: AnyContentAsJson({"upload":{"ok":"ASSEMBLY_COMP...

  request.body.asJson.map { json =>
    println()
    println(json)  // output: {"upload":{"ok":"ASSEMBLY_COMPLETED","assemb...

    (json \ "upload").asOpt[models.SomeClass].map { upload =>
      Ok("Got upload")
    }.getOrElse {
      BadRequest("Missing parameter [upload]")
    }
  }.getOrElse {
    BadRequest("Expecting Json data")
  }
}

我无法理解上述代码失败的原因。该方法可以轻松地将请求正文映射到 json 对象。“println(json)”命令打印出与 Chrome 显示的“请求有效负载”完全相同的内容。然而,当我尝试抓取根对象“上传”时,它失败了。该方法返回一个错误的请求,抱怨缺少参数。

4

2 回答 2

4

要做 asOpt[models.SomeClass] 需要有一个Reads实例才能工作。

这是一个例子

case class SomeClass(ok: String, assemblyId: String)
implicit object SomeClassReads extends Reads[SomeClass] {
  def reads(json: JsValue) = 
    SomeClass((json \ "ok").as[String], (json \ "assemblyId").as[String])
}

您可以在https://github.com/playframework/Play20/blob/2.0.x/framework/src/play/src/main/scala/play/api/libs/json/Reads查看如何实现 Reads 实例 .scala#L35

于 2012-11-17T01:43:54.737 回答
1

如果您使用 play 2.1x,Reads 与 2.0x 相比有所改变,这可能是您的主要问题(像我一样)。

你可以在这里找到一个很好的解释。

只需此代码即可正常工作:

import play.api.libs.json._
import play.api.libs.functional.syntax._

case class Person(name: String, age: Int, lovesChocolate: Boolean)

implicit val personReads = Json.reads[Person]

看起来很神奇不是吗?但是有几点需要注意:

  • 隐式定义应该在控制器中。当然,还有一些其他的方法可以做到这一点。

  • 如果您的模型在模型类中(在上面的示例中位于控制器中),则不应将对象命名为与您的类相同。在这种情况下,它不起作用:

    case class Person(name: String, age: Int, lovesChocolate: Boolean)    
    
    object Person{....}  //this won't work
    

这种方式有很大的优势。我强烈建议您查看博客。

于 2012-12-18T17:55:23.333 回答