我想实现一个解析和验证 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 docs中,我找不到一种方法,它允许我检查上一个身体解析器的结果并返回结果或继续到控制器。
答案 0 :(得分:10)
解析主体后,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
on它。我们的flatMap
方法将JsResult
从validate
转换为Either[JsError, A]
,因此我们只有A
的一半,之后我们map
将JsError
留给SimpleResult
,我们很高兴。
答案 1 :(得分:0)
好的,我已经通过生成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
做同样的事情,如果我需要这样做,或者它现在更好?