2

我想实现一个解析和验证 request.body的 BodyParser ,它基于parse.json并且目前看起来像这样:

def parseModel[A](implicit reads: Reads[A]): BodyParser[JsResult[A]] =
  parse.json.map(_.validate[A])

问题是它当前是 typeBodyParser[JsResult[A]]而我希望它是 type BodyParser[A]。如果JsError我希望它基本上返回400 Bad Request验证错误。

Play API 文档中,我找不到允许我检查先前正文解析器的结果并返回结果或继续到控制器的方法。

4

2 回答 2

10

A 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方法将JsResultfrom转换validate为 an Either[JsError, A],所以我们已经完成了一半A,然后我们map离开JsErrorto SimpleResult,我们就可以开始了。

于 2013-09-23T07:10:17.033 回答
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,如果我需要这样做,或者它现在更好吗?

于 2013-09-22T17:28:40.927 回答