/ / Декодиране gzipped JSON в Akka HTTP - json, scala, akka-http

Декодиране на gzipped JSON в Akka HTTP - json, scala, akka-http

Имам крайна точка, по която можем да се обадим /test който вътрешно извлича данни от API на трета странаи след това иска да извърши някаква трансформация, преди да върне отговор. Където съм затворил, този API на трета страна връща gzipped JSON и не мога да го декодирам (все още). Намерих директива decodeRequest но изглежда трябва да използвам това в маршрутизирането си и тук съм на ниво по-дълбоко. Имам вътрешен метод, на който се обаждам, след като получа a GET до крайната ми точка /test който е кръстен do3rdPartyAPIRequest където изграждам HttpRequest и преминете към Http().singleRequest() така че в замяна имам a Future[HttpResponse] където мисля, че искам да бъда, но съм заседнал тук.

С някои локални API, които изградих и консумирах по подобен начин, не кодирах отговорите си така обикновено с a Future[HttpResponse] Проверявам състоянието на отговора и преминавам към преобразуване в JSON чрез Unmarshal но тази се нуждае от допълнителна стъпка, доколкото знам, преди да се трансформира в JSON. Разбрах, че този въпрос е много подобен на този но това е специфично за спрея и аз не успях да преведа този отговор в текущия akka http

Отговори:

6 за отговор № 1

Най-накрая разбрах това - това може да не е абсолютно най-доброто за получаване на батерия от отговор, но работи. Оказва се, че можете да използвате Gzip клас

и имате две възможности

  1. Gzip.decode
  2. Gzip.decoderFlow

Ето моите примери в случай, че това ви помогне:

def getMyDomainObject(resp: HttpResponse):Future[MyDomain] = {
for {
byteString <- resp.entity.dataBytes.runFold(ByteString(""))(_ ++ _)
decompressedBytes <- Gzip.decode(byteString)
result <- Unmarshal(decompressedBytes).to[MyDomain]
} yield result
}


def getMyDomainObjectVersion2(resp:HttpResponse):Future[MyDomain] = {
resp.entity.dataBytes
.via(Gzip.decoderFlow)
.runWith(Sink.head)
.flatMap(Unmarshal(_).to[MyDomain])
}

2 за отговор № 2

Можете да очаквате, че компресираното съдържание ще се управлява от akka-http по подразбиране, но само осигурява PredefinedFromEntityUnmarshallers и вътре в субекта няма информация за Content-encoding глава.

За да разрешите това, трябва да внедрите свой собствен Unmarshaller и да го имате в обхвата

Пример:

implicit val gzipMessageUnmarshaller = Unmarshaller(ec => {
(msg: HttpMessage) => {
val `content-encoding` = msg.getHeader("Content-Encoding")
if (`content-encoding`.isPresent && `content-encoding`.get().value() == "gzip") {
val decompressedResponse = msg.entity.transformDataBytes(Gzip.decoderFlow)
Unmarshal(decompressedResponse).to[String]
} else {
Unmarshal(msg).to[String]
}
}
})