尝试解析Future响应时有什么问题?

tes*_*ser 3 scala future http response playframework

我有一个函数,它将通过ajax请求获取令牌.当令牌有效时,它将返回响应目录列表.

def all = Action.async(parse.json) {
  implicit request => tokenForm.bind(request.body).fold(
    formWithErrors => Future.successful(BadRequest(formWithErrors.toString)),
    form => checkToken(form.token).map(token => {
      val directories = Directories.all.map(directory => {
        Json.toJson(directory)
      })
      Ok(Json.obj("status" -> {if (token.get.id.getOrElse(0) >= 1) true else false}, "message" -> {if (token.get.id.getOrElse(0) >= 1) Json.toJson(directories) else "Invalid token"}))
    })
  )
}
Run Code Online (Sandbox Code Playgroud)

当我运行上面的代码它说[As ^符号表示错误发现的位置]

No Json serializer found for type scala.concurrent.Future[play.api.libs.json.JsValue]. Try to implement an implicit Writes or Format for this type.
Ok(Json.obj("status" -> {if (token.get.id.getOrElse(0) >= 1) true else false}, "message" -> {if (token.get.id.getOrElse(0) >= 1) Json.toJson(directories) else "Invalid token"}))
                                                                                                                                            ^
Run Code Online (Sandbox Code Playgroud)

Łuk*_*asz 5

这是我想出来的

def all = Action.async(parse.json) {
  implicit request => tokenForm.bind(request.body).fold(
    formWithErrors => Future.successful(BadRequest(formWithErrors.toString)),
    form => for {
      (token, directories) <- checkToken(form.token) zip Directories.all
    } yield {
      val isTokenValid = token.isDefined
      val responseBody = Json.obj(
        "status" -> isTokenValid, 
        "message" -> {
          if (isTokenValid)
            Json.toJson(directories)
          else
            "Invalid token"
        }
      )
      Ok(responseBody)
    }
  )
}
Run Code Online (Sandbox Code Playgroud)

asuming checkTokenDirectories.all回报Future.

你的功能需要返回Future[Result].折叠时,第一个分支是正确的

formWithErrors => Future.successful(BadRequest(formWithErrors.toString))
Run Code Online (Sandbox Code Playgroud)

但是在第二个分支中,您似乎通过调用启动了一个新的Future Directories.all,并且您希望将其序列化并返回为json.没有序列化器,Future[JsValue]因为这没有意义,它必须阻止获得结果.你需要以某种方式得到双方的价值观checkToken(form.token)Directories.all.

你可以像我上面那样做,或者像这样:

form => {
  val futureToken = checkToken(form.token)
  val futureDirectories = Directories.all

  for {
    token <- futureToken
    directories <- futureDirectories
  } yield {
     // same code as above
  }
}
Run Code Online (Sandbox Code Playgroud)

请注意,如果您将内联futureToken并且futureDirectories它们将按顺序执行.

另请注意,您要将目录列表转换为json两次.

来到这里

val directories = Directories.all.map(directory => {
  Json.toJson(directory)
})
Run Code Online (Sandbox Code Playgroud)

假设Directories.all返回Future[List[Directory]],那么当您使用时map,您传递的函数会运行,List[Directory]因此该变量应该命名为directoriesnot directory.它会工作,轻松转换任何可转换为json的列表,无需手动执行.

你第二次在这里做到了

Json.toJson(directories)
Run Code Online (Sandbox Code Playgroud)

  • 你也可以做`token.exists(_.id> 0)` (2认同)