我想实现一个解析和验证request.body
的 BodyParser,它基于 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文档中,我找不到允许我检查先前正文解析器的结果并返回结果或继续控制器的方法。
BodyParser
在解析主体后,会产生一个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
,我们就可以开始了。
,我已经通过一种产生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
做同样的事情,如果我需要这样做,或者像现在这样更好?