在ActionBuilder中将主体作为JSON访问

时间:2015-02-14 22:24:06

标签: json action playframework-2.3

我正在使用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

1 个答案:

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