我想从Json响应返回字符串

我想从Json响应返回字符串,json,scala,spray-client,Json,Scala,Spray Client,对不起,我是Scala的新手。我已经阅读了Futures和Akka的相关内容,但是我仍然无法为我的方法返回字符串 我有一个方法getAuthString,它应该返回身份验证字符串(或令牌)。 我使用了spray Jsonsupport,可以打印结果 def getToken(url: String, username: String , password: String) = Future[String]{ import MyJsonProtocol._ import spray.httpx.

对不起,我是Scala的新手。我已经阅读了Futures和Akka的相关内容,但是我仍然无法为我的方法返回字符串

我有一个方法getAuthString,它应该返回身份验证字符串(或令牌)。 我使用了spray Jsonsupport,可以打印结果

def getToken(url: String, username: String , password: String) = Future[String]{

import MyJsonProtocol._
import spray.httpx.SprayJsonSupport._

val pipeline: HttpRequest => Future[AuthTokenResult[Entry]] = (addCredentials(BasicHttpCredentials(username, password))
  ~> sendReceive
  ~> unmarshal[AuthTokenResult[Entry]]
  )
val myfutureResponse: Future[AuthTokenResult[Entry]] = pipeline(Get(url))

myfutureResponse onComplete {
      case Success(AuthTokenResult(Entry(Content(authString)):: _)) => println(authString)
      case Failure(error) => println("An error has occured: " + error.getMessage)
    }

这将解组json并打印所需的authString。然而,印刷对我没有好处。我知道一个完整的返回单元。我想返回authString,这样我就可以在其他地方与另一个请求一起使用它。我想我将不得不使用平面图或地图,但我不知道如何使用。我需要我的方法返回authString或error

你不想返回一个
字符串,你想返回一个
未来的[String]
——一旦某个东西是异步的,使它不异步的唯一方法就是阻塞,这(通常)是一种浪费,使得整个异步变得毫无意义

我也不知道你为什么要把整个事情包装在一个
未来
中——琐碎的计算可以自己进行,把它们强制放到一个单独的线程上没有什么价值。所以你想要的是:

def getToken(url: String, ...): Future[String] = {
  ...
  val myFutureResponse: Future[AuthTokenResult[Entry]] = ...
  myFutureResponse map {
    case AuthTokenResult(Entry(Content(authString))::_) => authString
  }
}
因此,您可以使用
map
通过计算将一个
Future
转换为另一个
Future
。这将“传递”错误,但如果要以特定方式处理这些错误,可以使用类似于
recover
recoverWith
的方法

然后,当您想在喷洒路线中使用
Future[String]
时,可以使用
onSuccess
onComplete
指令:

val myRoute = (path("/somewhere") & parameter("authData") {
  authData =>
    onSuccess(getToken(authData)) {
      authToken =>
        complete("Authed as " + authToken)
    }
  }

这将以适当的异步、反应式方式使用
未来
,而不会阻塞。

感谢@Imm的及时响应。你给了我足够多的建议,我很高兴你的回答,但是,请原谅我的无知。如果我使用路由方法,这意味着需要进行API调用/url/path+?authToken的所有代码都必须位于单个代码块中。为什么我不能使用Val mytoken=getToken(url,…)这样每当我需要发出API请求时,我就可以将令牌作为请求参数的一部分附加到我的url中。你说如果我这样做,这将是阻塞,问题是我最终将没有可重用的代码哦,我不知道你只是在使用spray客户端。您可以使用承诺来持有
authToken
val authToken=Promise[String]();authToken.completeWith(getToken())
然后在其他代码中使用
authToken.future
。或者你可以找个演员。或者您的代码根本不需要异步,在这种情况下,您只需执行
val authToken=wait.result(getToken(),30秒)
。在这种情况下,最好不要使用spray,因为它增加了高性能并行代码所需的复杂性,但简单的情况可以使用更简单的库。