我有一个Akka-Http路线,我正在调用Bing Search API。在将响应发送到客户端之前,我想在结果中添加一些额外的记录。我正在使用circe来处理json。 以下代码不起作用,但说明了这个想法:
val extraData = Map("key1"->"value1","key2"->"val2").asJson
val query = URLEncoder.encode(q, "utf8")
val responseFuture: Future[HttpResponse] = Http().singleRequest(
HttpRequest(uri = "https://api.cognitive.microsoft.com/bing/v7.0/search?q=" + query)
.withHeaders(RawHeader("Ocp-Apim-Subscription-Key", k1)))
val alteredResponse = responseFuture.map{ response => {
response.entity.toStrict(2 seconds) flatMap { e =>
e.dataBytes
.runFold(ByteString.empty) { case (acc, b) => acc ++ b }
.map(k => parse(k.utf8String)
match {
case Left(failure) => "Can't parse"
case Right(json) => Try {
json.hcursor.withFocus{
_.mapObject(x =>
x.add("extraData",extraData)
)
}
}}
)
}
}}
complete(alteredResponse)
这是一个很好的方法吗?我怎样才能让它发挥作用?
答案 0 :(得分:0)
我最终使用flatMap并手动创建HttpResponse对象:
val responseFuture: Future[HttpResponse] = Http().singleRequest(
HttpRequest(uri = "https://api.cognitive.microsoft.com/bing/v7.0/search?q=" + query)
.withHeaders(RawHeader("Ocp-Apim-Subscription-Key", k1)))
.flatMap{ response => {
response.entity.toStrict(2 seconds) flatMap { e =>
e.dataBytes
.runFold(ByteString.empty) { case (acc, b) => acc ++ b }
.map(k => parse(k.map(_.toChar).mkString)
match {
case Left(failure) => HttpResponse(
StatusCodes.OK,
List(),
HttpEntity("NO RESULTS".map(_.toByte).toArray),
HttpProtocol("HTTP/1.1")
)
case Right(json) => {
json.hcursor.withFocus{
_.mapObject(x =>
x.add("extraData",extraData)
)
}.top match {
case Some(jsn) => {
HttpResponse(
StatusCodes.OK,
List(headers.`Content-Type`(ContentType(MediaTypes.`application/json`,() => HttpCharsets.`UTF-8`))),
HttpEntity(jsn.noSpaces.toCharArray.map(_.toByte)),
HttpProtocol("HTTP/1.1")
)
}
}
}}
)
}
}}
complete(responseFuture)
当转换来自Bing的响应字节时,我试图使用.utf8String函数,但是它搞砸了Json,所以我用地图解析了字节。(_ toChar).mkString。
如果有更好的方法来编写此代码,那么很高兴看到它。感谢。