在Play Framework 2.0 Scala中处理JSON请求

时间:2012-11-17 01:28:27

标签: json scala playframework playframework-2.0

我正在尝试使用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显示为“请求有效负载”完全相同的内容。然而,当我尝试抓取根对象“上传”时,它失败了。并且该方法返回一个抱怨缺少参数的错误请求。

2 个答案:

答案 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博客。