Play 2.0 用戶指南 - 使用JSON庫 -- 針對Scala開發者


    概述


    使用JSON的推薦方式是使用 Play 的基於類的JSON庫,位於play.api.libs.json下.

    該庫構建於Jerkson之上,它是一個Scala包裝者,基於一個超快的基於Java的JSON庫,Jackson.html

    這種方式的好處是,Java和Scala能夠共享一樣的庫(Jackson),而Scala用戶能夠享受額外類型安全的好處。
    play.api.libs.json包中,包含了7個JSON數據類型:
        JsObject
        JsNull
        JsUndefined
        JsBoolean
        JsNumber
        JsArray
        JsString
   
    它們都繼承自JsValue。
   
    解析JSON字符串

    你能夠將任何的JSON字符串解析成JsValue。
val json: JsValue = Json.parse(jsonString)

    遍歷JSON樹


    只要你擁有一個JsValue,你就能夠遍歷該樹。該API看起來很像Scala提供的使用NodeSeq遍歷XML文檔的方式.
val json = Json.parse(jsonString)

val maybeName = (json \ "user" \ name).asOpt[String]
val emails = (json \ "user" \\ "emails").map(_.as[String])


   注意使用 \ 遍歷不會致使失敗.你必須在末尾使用 asOpt[T]自行處理出錯誤情形,它將返回 None 若是值缺失的話.不然,你能夠使用 as[T],以拋異常的方式處理失敗,若是值丟失的話.

    Scala值轉成Json

    As soon as you have a type class able to transform the Scala type to Json, it is pretty easy to

    generate any Scala value to Json. For example letʼs create a simple Json object: json

    只要你有一個type class 你就能將Scala類型轉成Json,很容易將任何的Scala值轉成Json.例如讓咱們建立一個簡單的Json對象: api

val jsonNumber = Json.toJson(4)

  或者建立Json數組 數組

val jsonArray = Json.toJson(Seq(1, 2, 3, 4))
    這裏將Seq[Int]轉成Json數組沒任何問題。然而當Seq由異構的值組成時,狀況將變得複雜:
val jsonArray = Json.toJson(Seq(1, "Bob", 3, 4))
    沒辦法將Seq[Any]轉成Json。(Any能夠是任何非Json格式支持的對象,對吧?)

    簡單的選擇是將它們作爲Seq[JsValue]處理:
val jsonArray = Json.toJson(Seq(
  toJson(1), toJson("Bob"), toJson(3), toJson(4)
))

    如今讓咱們看看最後一個建立更復雜的Json對象的例子:
val jsonObject = Json.toJson(
  Map(
    "users" -> Seq(
      toJson(
        Map(
          "name" -> toJson("Bob"),
          "age" -> toJson(31),
          "email" -> toJson("bob@gmail.com")
        )
      ),
      toJson(
        Map(
          "name" -> toJson("Kiki"),
          "age" -> toJson(25),
          "email" -> JsNull
        )
      )
    )
  )
)


    它將產生以下Json結果:
val jsonObject = Json.toJson(
  Map(
    "users" -> Seq(
      toJson(
        Map(
          "name" -> toJson("Bob"),
          "age" -> toJson(31),
          "email" -> toJson("bob@gmail.com")
        )
      ),
      toJson(
        Map(
          "name" -> toJson("Kiki"),
          "age" -> toJson(25),
          "email" -> JsNull
        )
      )
    )
  )
)

    Json序列化

    將JsValue轉成Json字符串形式很容易:
val jsonString: String = Json.stringify(jsValue)

    其它選擇

    上面討論的基於類型的選擇是推薦的形式,固然也不會限制你使用其它JSON庫。
   
    例如,下面是一小段演示怎樣將純Scala對象轉成JSON 對象,經過綁定的,基於反射的Jerkson。
import com.codahale.jerkson.Json._

val json = generate(
  Map( 
    "url"-> "http://nytimes.com",
    "attributes" -> Map(
      "name" -> "nytimes", 
      "country" -> "US",
      "id" -> 25
    ), 
    "links" -> List(
      "http://link1",
      "http://link2"
    )
  )
)


    處理Json請求


    處理Json請求

        一個 JSON 請求是一個使用 request body 搭載經驗證的JSON內容的 HTTP 請求.它必須指定 Content-Type 爲text/json或application/json mime類型。

    默認Action使用any content body parser,讓你以JSON取值得request body 值(其實是JsValue):
def sayHello = Action { request =>
  request.body.asJson.map { json =>
    (json \ "name").asOpt[String].map { name =>
      Ok("Hello " + name)
    }.getOrElse {
      BadRequest("Missing parameter [name]")
    }
  }.getOrElse {
    BadRequest("Expecting Json data")
  }
}


    更好的方法是自定義BodyParser,請求Play直接將body解析爲JSON:
def sayHello = Action(parse.json) { request =>
  (request.body \ "name").asOpt[String].map { name =>
    Ok("Hello " + name)
  }.getOrElse {
    BadRequest("Missing parameter [name]")
  }
}


    注意:當使用JSON body parser的時候,request.body的值直接作爲一個經驗證的JsValue值。

    你能夠經過在命令行中用curl測試:
curl 
  --header "Content-type: application/json" 
  --request POST 
  --data '{"name": "Guillaume"}' 
  http://localhost:9000/sayHello


    返回:
HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
Content-Length: 15

Hello Guillaume


    返回JSON響應


    前面的一些例子,咱們接收JSON請求,但咱們返回的是text/plain響應。
    讓咱們更改成一個有效的HTTP響應:
def sayHello = Action(parse.json) { request =>
  (request.body \ "name").asOpt[String].map { name =>
    Ok(toJson(
      Map("status" -> "OK", "message" -> ("Hello " + name))
    ))
  }.getOrElse {
    BadRequest(toJson(
      Map("status" -> "KO", "message" -> "Missing parameter [name]")
    ))
  }
}


    如今它返回:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: 43

{"status":"OK","message":"Hello Guillaume"}
相關文章
相關標籤/搜索