BodyParser根据请求体返回Result

时间:2013-09-22 14:15:54

标签: scala playframework playframework-2.0

我想实现一个解析和验证 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中,我找不到一种方法,它允许我检查上一个身体解析器的结果并返回结果或继续到控制器。

2 个答案:

答案 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方法将JsResultvalidate转换为Either[JsError, A],因此我们只有A的一半,之后我们mapJsError留给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做同样的事情,如果我需要这样做,或者它现在更好?