【问题标题】:BodyParser to return Result based on request bodyBodyParser 根据请求正文返回 Result
【发布时间】:2013-09-23 15:17:38
【问题描述】:
我想实现一个 BodyParser 来解析和验证request.body,它基于parse.json,目前看起来像这样:
def parseModel[A](implicit reads: Reads[A]): BodyParser[JsResult[A]] =
parse.json.map(_.validate[A])
问题是它目前是BodyParser[JsResult[A]] 类型,而我希望它是BodyParser[A] 类型。如果是JsError,我希望它基本上返回带有验证错误的400 Bad Request。
在Play API docs 中,我找不到允许我检查先前正文解析器的结果并返回结果或继续到控制器的方法。
【问题讨论】:
标签:
scala
playframework
playframework-2.0
【解决方案1】:
一个BodyParser,在解析body之后,产生一个Either[SimpleResult, A],其中SimpleResult是一个错误结果,应该立即返回而不是处理动作。 BodyParser 上的便捷方法不允许您这样做,因此,请创建一个新的主体解析器,委托给 JSON 主体解析器:
def validateJson[A](implicit reads: Reads[A]) = new BodyParser[A] {
def apply(request: RequestHeader) = parse.json(request).map(_.right.flatMap { json =>
json.validate[A].asEither.left.map(e => BadRequest(JsError.toFlatJson(e)))
})
}
您可以在这里看到我们正在映射解析的结果,然后获取right 值(成功解析,将是JsValue),并在其上调用flatMap。我们的flatMap 方法将JsResult 从validate 转换为Either[JsError, A],所以我们已经完成了A 的一半,然后我们将map 左边的JsError 转换为SimpleResult,然后我们'很好走。
【解决方案2】:
好的,我已经通过产生Action的方法实现了所需的行为:
def validateJson[A](implicit reads: Reads[A]) =
parse.json.map(_.validate[A])
def ModelAction[A](action: A => Result)(implicit r: Reads[A]) =
Action(validateJson[A]) { request =>
request.body match {
case JsSuccess(model, _) => action(model)
case JsError(e) => BadRequest(JsError.toFlatJson(e))
}
}
我可以这样使用它:
def create = ModelAction[MyModel] { model =>
???
}
我仍然感兴趣是否可以对 BodyParser 做同样的事情,如果我需要这样做,或者像现在这样更好?