我正在尝试使用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显示为“请求有效负载”完全相同的内容。然而,当我尝试抓取根对象“上传”时,它失败了。并且该方法返回一个抱怨缺少参数的错误请求。
答案 0 :(得分: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])
}
您可以在以下位置了解如何实现Reads实例 https://github.com/playframework/Play20/blob/2.0.x/framework/src/play/src/main/scala/play/api/libs/json/Reads.scala#L35
答案 1 :(得分:1)
如果你使用play 2.1x,Reads已经从2.0x改变了一点,这可能是你的主要问题(像我一样)。
您可以找到一个非常好的解释here。
只需这段代码就可以了:
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
这种方式有很大的优势。我强烈建议您查看this博客。