在 ActionBuilder 中以 JSON 访问正文
Access body as JSON in ActionBuilder
我正在使用 Playframework 2。3.X。我正在尝试构建一个动作函数来验证 JSON request.body 中的字段。用例是构建 "blocks" 验证,然后我可以将其链接在一起。
但是,我似乎无法在操作生成器中将 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
}
}
更新:也可能是我处理方法不对。我是新手,所以也欢迎其他方法。
更新:是的,看来 a 可能以错误的方式做事。我不是唯一遇到这个问题的人。参见 https://github.com/playframework/playframework/issues/3387
我认为你可能需要对体型进行模式匹配(我承认这不是一个很好的解决方案):
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
很好地组合,这可能是你最好的选择。
我正在使用 Playframework 2。3.X。我正在尝试构建一个动作函数来验证 JSON request.body 中的字段。用例是构建 "blocks" 验证,然后我可以将其链接在一起。
但是,我似乎无法在操作生成器中将 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
}
}
更新:也可能是我处理方法不对。我是新手,所以也欢迎其他方法。
更新:是的,看来 a 可能以错误的方式做事。我不是唯一遇到这个问题的人。参见 https://github.com/playframework/playframework/issues/3387
我认为你可能需要对体型进行模式匹配(我承认这不是一个很好的解决方案):
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
很好地组合,这可能是你最好的选择。