在 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 很好地组合,这可能是你最好的选择。