尝试解析 Future 响应时出了什么问题?
What is the wrong while trying to parse Future response?
我有一个函数可以通过 ajax 请求获取令牌。当令牌有效时,它将 return 响应目录列表。
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"}))
})
)
}
虽然我运行上面的代码它说[作为^符号指示发现错误的位置]
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"}))
^
这是我想出的
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)
}
)
}
假设 checkToken
和 Directories.all
returns Future
.
您的函数需要 return Future[Result]
。当你折叠时,第一个分支是正确的
formWithErrors => Future.successful(BadRequest(formWithErrors.toString))
然而,在第二个分支中,您似乎通过调用 Directories.all
开始了一个新的 Future,并且您想将其和 return 序列化为 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
}
}
请注意,如果您要内联 futureToken
和 futureDirectories
,它们将被串行执行。
另请注意,您将目录列表转换为 json 两次。
来过一次
val directories = Directories.all.map(directory => {
Json.toJson(directory)
})
假设Directories.all
returns Future[List[Directory]]
,那么当你使用map
时,你传递的函数在List[Directory]
上运行,所以变量应该被命名directories
不是 directory
。它会工作,轻松播放任何可转换为 json 的列表,无需手动执行。
你第二次在这里做了
Json.toJson(directories)
我有一个函数可以通过 ajax 请求获取令牌。当令牌有效时,它将 return 响应目录列表。
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"}))
})
)
}
虽然我运行上面的代码它说[作为^符号指示发现错误的位置]
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"}))
^
这是我想出的
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)
}
)
}
假设 checkToken
和 Directories.all
returns Future
.
您的函数需要 return Future[Result]
。当你折叠时,第一个分支是正确的
formWithErrors => Future.successful(BadRequest(formWithErrors.toString))
然而,在第二个分支中,您似乎通过调用 Directories.all
开始了一个新的 Future,并且您想将其和 return 序列化为 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
}
}
请注意,如果您要内联 futureToken
和 futureDirectories
,它们将被串行执行。
另请注意,您将目录列表转换为 json 两次。
来过一次
val directories = Directories.all.map(directory => {
Json.toJson(directory)
})
假设Directories.all
returns Future[List[Directory]]
,那么当你使用map
时,你传递的函数在List[Directory]
上运行,所以变量应该被命名directories
不是 directory
。它会工作,轻松播放任何可转换为 json 的列表,无需手动执行。
你第二次在这里做了
Json.toJson(directories)