我正在使用Playframework 2.3.X.我正在尝试构建一个动作函数来验证JSON request.body中的字段。用例是构建验证的“块”,然后我可以将它们链接在一起。
但是,我似乎无法在动作构建器中访问request.body作为JSON。以下内容无法编译。编译器无法解析“asJson”:
def ValidateJsonBodyAction = new ActionBuilder[Request] {
def invokeBlock[A](request: Request[A], block: (Request[A]) => Future[Result]): Future[Result] = {
val body= request.body.asJson
}
}
更新:也可能是我以错误的方式接近这一点。我是新手,所以也欢迎其他方法。
更新:是的,似乎可能是做错事。我不是唯一有这个问题的人。见https://github.com/playframework/playframework/issues/3387
答案 0 :(得分:2)
我认为你可能需要对身体类型进行模式匹配(我承认这不是一个漂亮的解决方案):
import scala.concurrent.Future.{successful => immediate}
def JsonValidator(validator: Reads[JsValue]) = new ActionBuilder[Request] {
def jsonBody[A](body: A): Option[JsValue] = body match {
case js: JsValue => Some(js)
case any: AnyContent => any.asJson
case _ => None
}
override def invokeBlock[A](request: Request[A], block: (Request[A]) => Future[Result]): Future[Result] = {
jsonBody(request.body) match {
case Some(js) => js.validate(validator) match {
case JsSuccess(_, _) => block(request)
case JsError(e) => immediate(BadRequest(s"Bad Json: $e"))
}
case None => immediate(UnsupportedMediaType("Bad content type: expected Json"))
}
}
}
这基本上就是你在幕后发生的事情,例如bind a form对任意和未知身体的请求。
另一方面您可能会发现只编写一个特定的BodyParser
来验证您的数据会更好,例如:
def jsonFormatParser(validator: Reads[JsValue]): BodyParser[JsValue] = parse.json.validate { js =>
js.validate(validator) match {
case JsSuccess(_, _) => Right(js)
case JsError(e) => Left(BadRequest(s"Json didn't have the right format: $e"))
}
}
// A validator which checks the JSON contains a "hello" path which
// then contains a "world" path
val helloWorldValidator: Reads[JsValue] = Reads.required(__ \ "hello" \ "world")
def helloWorldAction = Action(jsonFormatParser(helloWorldValidator)) { implicit request =>
Ok("Got the right type of JSON")
}
这取决于您的用例。由于JSON验证器(Reads[JsValue]
)可以通过andThen
很好地组合,这可能是您最好的选择。