2016-02-21 4 views
2

Я пытаюсь вызвать apo геокодирования google и получить ответ.Как прочитать ответ json от объекта ответа akka-http с помощью json4s

lazy val geoCodingConnectionFlow: Flow[HttpRequest, HttpResponse, Any] = 
    Http().outgoingConnectionHttps(config.getString("services.geoCodingApiHost"), config.getInt("services.geoCodingApiPort")) 

def geoCodingRequest(request: HttpRequest): Future[HttpResponse] = Source.single(request).via(geoCodingConnectionFlow).runWith(Sink.head) 
/** 
* This call to google service is limited 
* @see https://developers.google.com/maps/documentation/geocoding/#Limits 
*/ 
def ?(l: GeoLocation)(implicit ec: ExecutionContext): Future[Either[String, List[Result]]] = { 
    val latlang = s"17.3644264,78.3896741" 
    import org.json4s.native.Serialization 
    import org.json4s.NoTypeHints 
    import akka.http.scaladsl.model._ 
    import akka.http.scaladsl.unmarshalling._ 
    implicit val materializer = ActorMaterializer() 
    implicit val executor = system.dispatcher 
    implicit val formats = Serialization.formats(NoTypeHints) 
    geoCodingRequest(RequestBuilding.Get(s"${config.getString("services.geoCodingApiUrlPart")}?latlng=$latlang&key=${config.getString("services.geoCodingApiKey")}")).flatMap { response => 
    val nonBinaryType = ContentTypes.`application/json` 
    def responseEntity: HttpEntity = response.entity 
    response.status match { 
     case OK if (response.entity.contentType == ContentTypes.`application/json`) => Unmarshal(response.entity).to[List[Result]].map(Right(_)) 
     case BadRequest => Future.successful(Left(s"$latlang: incorrect Latitude and Longitude format")) 
     case _ => Unmarshal(response.entity).to[String].flatMap { entity => 
     val error = s"Google GeoCoding request failed with status code ${response.status} and entity $entity" 
     Future.failed(new IOException(error)) 
     } 
    } 
    } 
} 

}

Я получаю следующее сообщение об ошибке компиляции при попытке выполнить это!

Service.scala:78: could not find implicit value for parameter um: akka.http.scaladsl.unmarshalling.Unmarshaller[akka.http.scaladsl.model.ResponseEntity,List[com.thenewmotion.geocode.Result]] 
      case OK if(response.entity.contentType == ContentTypes.`application/json`)=> Unmarshal(response.entity).to[List[Result]].map(Right(_)) 

Пожалуйста, помогите мне, чтобы получить результат разобранное на следующие классы дела Результат:

package com.thenewmotion.geocode 

case class Address(
    long_name: String, 
    short_name: String, 
    types: List[String] 
) 

case class Result(
    address_components: List[Address], 
    formatted_address: String, 
    types: List[String] 
) 

case class Response(
    results: List[Result], 
    status: Status 
) { 
    def allResults = status match { 
    case Ok => Right(results) 
    case e: Error => Left(e) 
    } 
} 

/** @see https://developers.google.com/maps/documentation/geocoding/#StatusCodes */ 
sealed trait Status 

case object Ok extends Status 

sealed trait Error extends Status 
case object ZeroResults extends Error 
case object OverQuotaLimit extends Error 
case object Denied   extends Error 
case object InvalidRequest extends Error 
case class OtherError(description: String) extends Error 

                                ^

ответ

5

Как сказано в сообщении об ошибке, вам необходимо предоставить неявный Unmarshaller[akka.http.scaladsl.model.ResponseEntity,List[com.thenewmotion.geocode.Result]] иначе структура не будет знать как преобразовать объект ответа в вашу модель List[com.thenewmotion.geocode.Result].

В качестве альтернативы, вы можете использовать встроенный в unmarshaller, чтобы преобразовать объект в строку, а затем использовать спрей-JSON для разбора строки JSON в целевой модели:

import akka.http.scaladsl.unmarshalling.Unmarshal 
import spray.json._ 

implicit val modelJsonReader = new JsonReader[List[com.thenewmotion.geocode.Result]] { 
// See https://github.com/spray/spray-json on how to implement JsonReader 
} 

def parseJson(str: String): List[com.thenewmotion.geocode.Result] = { 
    // parse using spray-json 
    str.parseJson.convertTo[List[com.thenewmotion.geocode.Result]] 
} 

response.status match { 
    case OK if (response.entity.contentType == ContentTypes.`application/json`) => 
    Unmarshal(response.entity).to[String].map { jsonString => 
     Right(parseJson(jsonString)) 
    } 
    case BadRequest => Future.successful(Left(s"$latlang: incorrect Latitude and Longitude format")) 
    case _ => Unmarshal(response.entity).to[String].flatMap { entity => 
    val error = s"Google GeoCoding request failed with status code ${response.status} and entity $entity" 
    Future.failed(new IOException(error)) 
    } 
} 

 Смежные вопросы

  • Нет связанных вопросов^_^