我正致力于持久性Action
。在其中我需要调用WS,通过邮政代码确定位置:
我从请求中收到的邮政编码,我使用的处理:
def futureLocationForPostCode(postcode: String): Option[Location] = {
val postcodeWithoutSpace = postcode.replaceAll(" ", "");
val url = "http://uk-postcodes.com/postcode/"+postcodeWithoutSpace+".json"
val holder: WSRequestHolder = WS.url(url)
val futureResponse: Future[WSResponse] = holder.get()
val result = futureResponse match {
case response: WSResponse => response.status match {
case 200 => {
val lat = (response.json \ "geo" \ "lat").as[Double]
val lon = (response.json \ "geo" \ "lng").as[Double]
val location: Location = Location(lat, lon)
location
}
case _ => None
}
}
result
}
这是Location
的模型:
case class Location(lat: Double, lon: Double)
object Location {
implicit val locationReads: Format[Location] = (
(JsPath \ "lat").format[Double](min(-90.0) keepAnd max(90.0)) and
(JsPath \ "lon").format[Double](min(-180.0) keepAnd max(180.0))
)(Location.apply, unlift(Location.unapply))
}
如果Action
中没有“无”,我就不知道如何保存位置:
def createAccount = Action.async {
implicit request => {
createAccountForm.bindFromRequest fold (
formWithErrors => {
Logger.info("Validation errors")
Future.successful(BadRequest(createAccountForm.errorsAsJson))
},
accountInfo => {
AccountService.findByEmail(accountInfo.email) map {
case accountOpt: Option[Account] => accountOpt match {
case Some(acc) => BadRequest(Json.toJson(Json.obj("message" -> "Email is already in use")))
case None => {
Logger.info("Created account")
val account = Account.createAccount(accountInfo)
//TODO: Add location to account if it is not None
val futureLocation = Account.futureLocationForPostCode(accountInfo.postCode)
Created(Json.toJson(AccountService.add(account)))
}
}
case _ => {
Logger.info("DB connection error")
InternalServerError(Json.toJson(Json.obj("message" -> "DB connection error")))
}
}
})
}
}
答案 0 :(得分:1)
您为futureLocationForPostCode方法假定了错误的返回类型。以下应该有效:
def futureLocationForPostCode(postcode: String): Future[Option[Location]] = {
val postcodeWithoutSpace = postcode.replaceAll(" ", "");
val url = "http://uk-postcodes.com/postcode/"+postcodeWithoutSpace+".json"
val holder: WSRequestHolder = WS.url(url)
val futureResponse: Future[WSResponse] = holder.get()
val result = futureResponse map { response =>
response.status match {
case 200 => {
val lat = (response.json \ "geo" \ "lat").as[Double]
val lon = (response.json \ "geo" \ "lng").as[Double]
val location: Location = Location(lat, lon)
Some(location)
}
case _ => None
}
}
result
}
然后
val futureLocation = Account.futureLocationForPostCode(accountInfo.postCode)
// Action.async requires a result of Future[SimpleResult] so map the future accordingly
futureLocation map { locationOption =>
val json = locationOption match {
case Some(location) => {
// here you can add location to account before return
Json.toJson(AccountService.add(account))
}
case None => {
Json.toJson(AccountService.add(account))
}
}
Created(json)
}