我试图像Akka http客户端一样使用Flow,并遇到从http响应中的json数组获取case类对象的Seq的麻烦。
HTTP响应:
{
"bars": [],
"foos": [
{
"id": "a7d1ba80-0934-11e9-0ef9-efa612d204a1",
"type": "manual",
"color": "green",
},
{
"id": "b7d1ba80-0934-11e9-0ef9-efa612d204a2",
"type": "semi-manual",
"color": "white"
}
]
}
案例课程:
case class FooResponse(foos: Seq[Foo])
case class Foo(id: String, type: String, color: String)
我做过的客户:
private val flow: Flow[HttpRequest, HttpResponse, Future[Http.OutgoingConnection]] = Http().outgoingConnection(host, port)
def getFoos(): Seq[Foo] = {
val req = HttpRequest(method = HttpMethods.GET)
.withUri(Uri("/api/foo")).withHeaders(headers.Accept(MediaRange(MediaTypes.`application/json`)))
Source
.single(req)
.via(flow)
.map(response => Unmarshal(response.entity).to[FooResponse])
}
因此,我有一个带有Future [FooResponse]的源。如何从中返回Seq [Foo]作为函数结果。
答案 0 :(得分:2)
我建议将[16:39:21] Possible Unhandled Promise Rejection (id: 0):
[16:39:21] Object {
[16:39:21] "D": 5,
[16:39:21] }
[16:39:21]
的返回类型从getFoos
更改为Seq[Foo]
,以便停留在Future[Seq[Foo]]
的上下文中:
Future
此外,由于def getFoos(): Future[Seq[Foo]] = {
val req =
HttpRequest(method = HttpMethods.GET)
.withUri(Uri("/api/foo"))
.withHeaders(headers.Accept(MediaRange(MediaTypes.`application/json`)))
Source
.single(req)
.via(flow)
.map(response => Unmarshal(response.entity).to[FooResponse])
.mapAsync(parallelism = 1)(fooResponse => fooResponse.map(_.foos))
.runWith(Sink.head)
}
是Scala中的保留关键字,因此您需要将其包装在type
案例类的反引号中:
Foo
答案 1 :(得分:1)
type
是关键字(类型别名),不应用作变量名onComplete()
上调用Future
方法以等待结果。为此,我们可以在getFoos()
-var fs: Seq[Foo] = Nil
中定义一个占位符。将来,我们会添加onComplete(tfr => fs = tfr.get.foos)
,然后等待一段时间:Await.result(f, Duration(5000, "millis"))
(在此示例中最多5s)。最后,我们可以返回占位符中的内容。这应该可以完成工作:
def getFoos(): Seq[Foo] = {
var fs: Seq[Foo] = Nil
val req = HttpRequest(method = HttpMethods.GET)
.withUri(Uri("/api/foo")).withHeaders(headers.Accept(MediaRange(MediaTypes.`application/json`)))
val f = Source
.single(req)
.via(flow)
.map(response => Unmarshal(response.entity).to[FooResponse])
f.onComplete(tfr => fs = tfr.get.foos)
Await.result(f, Duration(5000, "millis"))
fs
}