2016-05-08 48 views
2

如何以類型安全的方式映射play-ws異步web請求的JSON響應?玩ws如何以類型安全的方式映射響應

private def webRequest(): Map[String, Any] = { 

    case class QuantileResult(val_05: Double, val_25: Double, val_50: Double, val_75: Double, val_90: Double) 

    object QuantileResult { 
     implicit val quantileResultFormat = Json.format[QuantileResult] 
    } 

    implicit val quantileReads = Json.reads[QuantileResult] 

    val payload = Json.obj(
     "json" -> Json.parse("""{"type":1,"x":[1,2,3,4,5,6,7,8,9,10],"probs":[0.05,0.25,0.75,0.95]}"""), 
     "windowWidth" -> JsNumber(11) 
    ) 

    wsClient.url("http://public.opencpu.org/ocpu/library/stats/R/quantile/json") 
     .withHeaders("Content-Type" -> "application/json") 
     .post(payload) 
     .map { wsResponse => 
     if (!(200 to 299).contains(wsResponse.status)) { 
      sys.error(s"Received unexpected status, open-cpu error ${wsResponse.status} : ${wsResponse.body}") 
     } 
     println(s"OK, received ${wsResponse.body}") 
     wsResponse.json.validate[QuantileResult] 
     match { 
      case JsSuccess(arrOut: QuantileResult, _) => QuantileResult //TODO how to perform mapping here to Map[String, Any] 
      case e: JsError => JsError.toFlatForm(e) // TODO empty array does not work here otherwise future[object] does not conform to expected return type of Map[String, Any] 
     } 
     } 
    } 
  1. 這裏怎麼執行映射到地圖[字符串,任何]
  2. 空地圖並不在這裏工作,否則未來[對象]不符合地圖的預期收益類型[字符串,任何]

什麼工作是

wsClient.url("url").withHeaders("Content-Type" -> "application/json").post(payload).map { wsResponse => result = wsResponse.body } 

     val json = Json.parse(result) 
     val mapper = new ObjectMapper() with ScalaObjectMapper 
     mapper.registerModule(DefaultScalaModule) 
     val returnValue = mapper.readValue[Map[String, Any]](result) 

但是,這似乎是真的笨重,不是異步。

回答

0

的解決方案是通過Await.result(someMethod), 20.seconds)

方法簽名更改爲正確的未來Future[Seq[Map[String, Any]]]並解決它像

wsResponse.json.validate[Seq[OutlierResult]] match { 
      case JsSuccess(result, _) => result.map(outlierRes => Map("period" -> outlierRes.period, "amount" -> outlierRes.amount, "outlier" -> outlierRes.outlier)) 
      case JsError(error) => throw new OutlierParseException(error.toString()) 
     } 

即使這可能提高到不拋出異常進行映射

+0

事實上,這不是最好的解決方案,例如例外情況不好處理。但它的工作。 –