簡體   English   中英

如何在Play框架中使用Scala將JsValue轉換為Model類?

[英]How to convert JsValue to a Model Class with Scala in Play framework?

我試圖設置一個從天氣API獲得的JSON響應以適合我定義的模型類,以便輕松使用它,但是我做不到。

這是課程:

import play.api.libs.json._
import play.api.libs.functional.syntax._

case class Forecast(var main: String, var description: String, var temp: Int, var tempMin: Int, var tempMax: Int)

object Forecast {
  implicit val forecastJsonFormat: Reads[Forecast] = (
      (JsPath \ "weather" \\"main").read[String] and
        (JsPath \ "weather" \\"description").read[String] and
        (JsPath \ "main" \\"temp").read[Int] and
        (JsPath \ "main" \\"temp_min").read[Int] and
        (JsPath \ "main" \\"temp_max").read[Int]
    ) (Forecast.apply _)
}

這是控制器中的代碼:

def weather = Action.async {
futureResponse.map(response => {
  val jsonString = response.json.toString()
  val jsonObject = Json.parse(jsonString)

  // TODO: Create t [Forecast] Object which represents the response.json data to send it to the view  below

  Ok(views.html.weather(t))
})}

我得到的response.json的示例:

{"coord":{"lon":37.62,"lat":55.75},"weather":[{"id":600,"main":"Snow","description":"light snow","icon":"13n"},{"id":701,"main":"Mist","description":"mist","icon":"50n"}],"base":"stations","main":{"temp":269.15,"pressure":1024,"humidity":92,"temp_min":268.15,"temp_max":270.15},"visibility":3100,"wind":{"speed":2,"deg":200},"clouds":{"all":90},"dt":1546266600,"sys":{"type":1,"id":9029,"message":0.0029,"country":"RU","sunrise":1546235954,"sunset":1546261585},"id":524901,"name":"Moscow","cod":200}

您必須將main更改為Seq[String]並將description更改為Seq[String]並將temptempMintempMaxDouble

我在這里使用了一種不同的方式來創建reads ,但是如果格式與預期的格式不同,則這種方式將引發異常。

case class Forecast(main: Seq[String], description: Seq[String], temp: Double, tempMin: Double, tempMax: Double)

object Forecast {
    val reads = new Reads[Forecast] {
        override def reads(json: JsValue): JsResult[Forecast] = {
            val main = (json \ "weather" \\ "main").map(_.as[String]).toList
            val description = (json \ "weather" \\ "description").map(_.as[String]).toList
            val temp = (json \ "main" \ "temp").as[Double]
            val tempMin = (json \ "main" \ "temp_min").as[Double]
            val tempMax = (json \ "main" \ "temp_max").as[Double]

            JsSuccess(Forecast(main, description, temp, tempMin, tempMax))
        }
    }
}

或者您可以使用相同的方式,但以不同的方式解析列表:

val forecastJsonFormat: Reads[Forecast] = (
  (JsPath \ "weather").read[List[Map[String, JsValue]]].map(_.map(_("main").as[String])) and
    (JsPath \ "weather").read[List[Map[String, JsValue]]].map(_.map(_("description").as[String])) and
    (JsPath \ "main" \ "temp").read[Double] and
    (JsPath \ "main" \ "temp_min").read[Double] and
    (JsPath \ "main" \ "temp_max").read[Double]
  ) (Forecast.apply _)

我終於要做到了,這是怎么做的:

在模型中,我定義了我的案例類和一個伴侶對象,該對象解析從Web API到我的類參數的JSON響應

型號代碼:

import play.api.libs.json._
import play.api.libs.functional.syntax._

case class Forecast(main: String, description: String, temp: Double, tempMin: Double, tempMax: Double)

object Forecast {
  implicit val forecastReads: Reads[Forecast] = (
      (JsPath \ "weather" \\ "main").read[String] and
      (JsPath \ "weather" \\ "description").read[String] and
      (JsPath \ "main" \ "temp").read[Double] and
      (JsPath \ "main" \ "temp_min").read[Double] and
      (JsPath \ "main" \ "temp_max").read[Double]
    ) (Forecast.apply _)
}

在控制器代碼中,我添加了一個模式匹配,在這里!

控制器代碼:

def weather = Action.async {
    futureResponse.map(response => {
      val parseResult = Json.fromJson[Forecast](response.json)
      parseResult match {
        case JsSuccess(forecast, JsPath) => Ok(views.html.weather(forecast))
        case JsError(error) => InternalServerError("Something went wrong!!") // Note that I'm not sure this result exists in Play...
      }
    })
  }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM