Play for Scala:捕获 HTTP JSON 请求错误

Play for Scala: Catch HTTP JSON request error

在下面的代码中,我收到一个 json 格式的 http request 并将其转换为 class MyRequest 的对象。如果所有字段都出现在 json 请求中,这会正常工作,但是如果缺少一个或多个字段,则会因 JsResultException 而崩溃。捕获错误的最佳方法是什么?

  request => val json = request.body
  val req = json.as[MyRequest]

而不是 as[T] 使用 validate[T],这会给你一个 JsResult[T]。在 Play 文档 here.

中对此进行了解释

从那里,您可以 fold 它并优雅地处理问题。通常我喜欢将问题摘要发送回调用者 作为 JSON,这比“500 - 内部服务器错误” 要好得多使用 as[T] 时获得的 HTML 页 。至少,通过返回 4xx 代码而不是 500,它把责任推给了 调用者 - 是他们给我们发送了无效 JSON 毕竟!

示例:

/** 
 * You can use this method as the error 
 *  handler wherever you fold on a validate[T]  
 */
def handleBadJson(problems:Seq[(JsPath, Seq[ValidationError])]):Future[Result] = {
  val jsProblems = problems.map { case(path, errs) =>
    val jsErrs = errs.map(err => JsString(err.message))
    path.toString -> JsArray(jsErrs)
  }

  Future.successful(BadRequest(JsObject(jsProblems)))
}

def doSomethingWithJsonRequest = Action.async(parse.json) { request =>
  request.body.validate[Foo].fold(handleBadJson, goodFoo => {
    ...
  })
}

我个人更喜欢搭配火柴的建筑。或许你也会喜欢

def doSomethingWithJsonRequest = Action(parse.json) { request =>
    request.body.validate[FooRequest] match {
      case s: JsSuccess[FooRequest] =>
        Ok(processFoo(s.get))
      case e: JsError =>
        BadRequest(handleError(e))
    }
}