2016-12-04 291 views
0

我試圖封送阿卡HttpResponse這樣:元帥阿卡`HttpResponse`作爲淘金者'Json`

{ 
    "code": 200, 
    "headers": [], 
    "body": "{\"data\": \"Yes!\"}" 
} 

如果我寫的淘金EncodeJson對於這種情況下,它可能是這樣的:

implicit def httpResponseEncodeJson: EncodeJson[HttpResponse] = 
    EncodeJson(
    (res: HttpResponse) ⇒ { 
     ("code" := res._1.value) ->: 
     ("headers" := res._2.toList) ->: 
     ("body" := res._3) ->: jEmptyObject 
    } 
) 

我設法將頭部編組爲json。唯一的問題是身體,即 ResponseEntity。由於它是一個阿克卡流,如果我使用.toStrict,它只能返回未來。

任何人都可以指導我如何編組嗎?

回答

0

如果可能,我會保留編組值作爲Future,以保留實體提取的異步性。

我會通過具有沿的

case class StrictHttpResponse(code: String, headers: List[HttpHeader], body: String) 

    def toStrictResponse(response: HttpResponse): Future[StrictHttpResponse] = response.entity.dataBytes.runFold(ByteString(""))(_ ++ _).map { bs => 
    StrictHttpResponse(response.status.value, response.headers.toList, bs.utf8String) 
    } 

    implicit def httpResponseEncodeJson: EncodeJson[StrictHttpResponse] = 
    EncodeJson(
     (res: StrictHttpResponse) ⇒ { 
     ("code" := res.code) ->: 
      ("headers" := res.headers) ->: 
      ("body" := res.body) ->: jEmptyObject 
     } 
    ) 

    def encodeResponse(response: HttpResponse): Future[Json] = toStrictResponse(response).map(_.jencode) 

線的東西開始,然後 - 例如 - 通過提供回調來處理encodeResponse的結果。

+0

非常感謝您的回答。我認爲我做了幾乎相同的事情。你能回顧我的答案嗎? –

0

我最終用這樣的:

implicit def httpResponseListMarshal: ToEntityMarshaller[List[HttpResponse]] = 
Marshaller { implicit ec ⇒ (responses: List[HttpResponse]) ⇒ 

    // Sink for folding Source of ByteString into 1 single huge ByteString 
    val sink = Sink.fold[ByteString, ByteString](ByteString.empty)(_ ++ _) 

    // A List of Future Json obtained by folding Source[ByteString] 
    // and mapping appropriately 
    val listFuture: List[Future[Json]] = for { 
     res ← responses 
    } yield for { 
     byteString ← res._3.dataBytes runWith sink 
     string = byteString.utf8String 
    } yield ("code" := res._1.intValue) ->: 
     ("headers" := res._2.toList) ->: 
     ("body" := string) ->: jEmptyObject 


    // Convert List[Future[Json]] to Future[List[Json]] 
    val futureList: Future[List[Json]] = Future.sequence(listFuture) 

    // ToEntityMarshaller is essentially a Future[List[Marshalling[RequestEntity]]] 
    for { 
     list ← futureList 
     json = jArray(list).nospaces 
    } yield List(
     Marshalling.Opaque[RequestEntity](() ⇒ 
     HttpEntity(`application/json`, json) 
    ).asInstanceOf[Marshalling[RequestEntity]] 
) 
} 

完整的代碼和樣本的使用可以在這裏找到: https://github.com/yashsriv/akka-http-batch-api/blob/argonaut/src/main/scala/org.yashsriv/json/Batch.scala