如何从 Akka 客户端 HttpResponse 解析 json 正文

How can I parse the json body from from an Akka Client-Side HttpResponse

我正在使用 Akka 的 HTTP 客户端库来请求 json,我想使用 Play Framework 的 play-json 来解析 json。拿到Akka的HttpResponse后,不知道如何从响应体中解析json,也不知道如何将json传递给[中的另一个函数=14=] 指令。相反,我得到这个错误

overloaded method value parse with alternatives:
[error]   (input: Array[Byte])play.api.libs.json.JsValue <and>
[error]   (input: java.io.InputStream)play.api.libs.json.JsValue <and>
[error]   (input: String)play.api.libs.json.JsValue
[error]  cannot be applied to (scala.concurrent.Future[String])
[error]           val usefulInfo = Json.parse(data)
[error]                                 ^
[error] one error found
[error] (Compile / compileIncremental) Compilation failed

我现在正在尝试的是:

import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.model._
import akka.stream.ActorMaterializer
import akka.http.scaladsl.model.HttpRequest
import akka.http.scaladsl.unmarshalling.Unmarshal
import play.api.libs.json._

object Main extends App {
    // Boilerplate code from Akka's documentation
    implicit val system = ActorSystem()
    implicit val materializer = ActorMaterializer()
    // needed for the future flatMap/onComplete in the end
    implicit val executionContext = system.dispatcher

    val request = HttpRequest(
        method = HttpMethods.GET,
        uri = "http://example.com/somedata.json"
    )
    var response: Future[HttpResponse] = Http().singleRequest(request)
    response.onComplete{
        case Success(res) => {
            val data = Unmarshal(res).to[String]
            val usefulInfo = Json.parse(data)
            println(usefulInfo)
        }
        case Failure(e)   => println(e)
    }
}

我的问题是:

  1. 如何在 Future 解析后使用 Play Framework 的 Json.parse() 解析 json?
  2. response 未来结算后,我如何在别处存储或使用此 json?在 Success 情况下我需要做些什么吗?

主要问题是Unmarshal returns一个Future所以你需要处理Future里面的数据得到String值。

如果您想保留结果而不只是打印它,请在初始结果上使用 tranformWith 而不是 onComplete:

val result = Http().singleRequest(request)
  .transformWith {
    case Success(res) =>
      val data = Unmarshal(res).to[String]

      data.map { d =>
        val usefulInfo = Json.parse(d)

        println(usefulInfo)

        usefulInfo
      }
    case Failure(e) =>
      println(e)

      Future.failed(e)
  }

请注意,如果您将打印留到最后,这会变得更加清晰:

val result = Http().singleRequest(request)
  .flatMap { res =>
    Unmarshal(res).to[String].map { data =>
      Json.parse(data)
    }
  }

result.onComplete {
  case Success(js) =>
    println(s"Success: $js")
  case Failure(e) =>
    println(s"Failure: $e")
}