2015-12-16 15 views
5

Pracuję ze starszym API HTTP (którego nie mogę zmienić), który reaguje z JSON w ciele, ale daje nagłówek Content-Type: text/plain; charset=utf-8.Jak rozpakować `text/plain` jako JSON w Akka HTTP

Ja próbuje wycofać to ciało HTTP jako JSON, ale pojawia się następujący wyjątek: akka.http.scaladsl.unmarshalling.Unmarshaller$UnsupportedContentTypeException: Unsupported Content-Type, supported: application/json

Mój kod wygląda następująco:

import spray.json.DefaultJsonProtocol 
import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._ 
import akka.http.scaladsl.unmarshalling._ 

case class ResponseBody(status: String, error_msg: String) 

object ResponseBodyJsonProtocol extends DefaultJsonProtocol { 
    implicit val responseBodyFormat = jsonFormat2(ResponseBody) 
} 

def parse(entity: HttpEntity): Future[ResponseBody] = { 
    implicit val materializer: Materializer = ActorMaterializer() 
    import ResponseBodyJsonProtocol._ 
    Unmarshal[HttpEntity](entity).to[ResponseBody] 
} 

Odpowiedź próbka HTTP wygląda następująco:

HTTP/1.1 200 OK 
Cache-Control: private 
Content-Encoding: gzip 
Content-Length: 161 
Content-Type: text/plain; charset=utf-8 
Date: Wed, 16 Dec 2015 18:15:14 GMT 
Server: Microsoft-IIS/7.5 
Vary: Accept-Encoding 
X-AspNet-Version: 4.0.30319 
X-Powered-By: ASP.NET 

{"status":"1","error_msg":"Missing parameter"} 

Co mogę zrobić, aby zignorować wartość Content-Type w odpowiedzi HTTP i przeanalizować jako JSON?

Odpowiedz

6

Jeden obejście znalazłem tylko ręcznie ustawić Content-Type na HttpEntity przed unmarshalling go:

def parse(entity: HttpEntity): Future[ResponseBody] = { 
    implicit val materializer: Materializer = ActorMaterializer() 
    import ResponseBodyJsonProtocol._ 
    Unmarshal[HttpEntity](entity.withContentType(ContentTypes.`application/json`)).to[ResponseBody] 
} 

wydaje się działać OK, ale jestem otwarty na inne pomysły ...

+0

Miałem podobny problem i wykorzystałem ostatnią linię kodu do Unmarshalling. Z jakiegoś powodu parametr withContentType zmienia obiekt i transformuje go do ścisłej jednostki, która zawiera także obiekt typu zawartości. Masz pomysł, jak wydobyć ciało z tego? –

2

I użyje dyrektywy map.... Wygląda krótko i elegancko.

val routes = (decodeRequest & encodeResponse) { 
    mapResponseEntity(_.withContentType(ContentTypes.`application/json`)) { 
    nakedRoutes ~ authenticatedRoutes 
    } 
} 
+0

Nie jestem pewien, czy to dotyczy ... w moim przypadku nie ma routingu, a ja na pewno nie widzę, jak to jest krótsze lub bardziej eleganckie niż moja odpowiedź. Sam pomysł. –

+1

O tak, jeśli nie używasz Spray DSL, to nie ma zastosowania. – expert