假设JSON是响应格式,我通常开始在case类中包装响应结构。
假设以下JSON响应:
{
"city": "Vienna",
"forecast": 10
}
现在这个案子看起来是这样的:
case class WeatherUpdate(city: String, forecast: Int)
使用singleton进行API调用的策略非常好。我们给他打电话
WeatherService
Future[Boolean]
您可以使用Scala标准库
Try
.
class WeatherService @Inject() (ws: WSClient) {
private val logger = Logger(getClass)
def getWeather(): Future[Try[WeatherUpdate]] = {
ws.get("https://myweather.com/api/update") // this is all fake
.map {
case response if response.status == 200 =>
val city = (response.json \ "city").as[String]
val forecast = (response.json \ "forecast").as[Int]
Success(WeatherUpdate(city, forecast))
case response =>
Failure(new WeatherException("Could not get weather response"))
}.recover { // always recover from a future. It could throw an exception and you would never know
case ex: Exception =>
logger.error("could not get weather info", ex)
Failure(ex)
}
}
}
class WeatherException(message: String) extends RuntimeException(message: String)
在控制器上,现在可以使用天气更新渲染模板:
def verify(code: String): Action[AnyContent] = Action.async {
implicit request =>
weatherService.getWeather().map {
case Success(weatherUpdate) => Ok(weather_template(weatherUpdate))
case Failure(ex) => BadRequest(weather_error())
}
}