Play 2.0 中文資料 - Play JSON 庫

Play 2.0 中文資料 - Play JSON 庫

2013-01-13 — Yanbin

概述

推薦的處理  JSON 的方式是使用 Play 基於 JSON 庫的類型類, 位置在 play.api.libs.json.

這個庫是構建於 Jerkson, 之上的,它又是基於 Java 的超快的 JSON 庫 Jackson 的 Scala 封閉。

Unmi 注:在 Play 1.x 所用的 JSON 庫是 Gson,而 Play 2.0 後更換成了 Jackson。還得 Play 2.0 是基於 SBT 構建的,所以 Play 2.0 的所有的 jar 都是在 $PLAY_HOME/repository/local 目錄中。

這樣做的好處是無論是 Java 還是 Scala 的 Play 應用依賴了相同的底層庫 (Jackson), 同時 Scala 用戶可以享受到  Play’s JSON 所帶來的額外的類型安全性.

play.api.libs.json 包含有七種 JSON 數據類型:

  • JsObject
  • JsNull
  • JsUndefined
  • JsBoolean
  • JsNumber
  • JsArray
  • JsString

上面的類型都繼承自通用的 JSON 值類型, JsValue.

解析 Json 字符串

你可很輕易的解析任意的 JSON 字符串爲一個 JsValue:

1
valjson:JsValue =Json.parse(jsonString)

遍歷  Json 樹

一旦你得到了一個 JsValue 你就可以遍歷這個 Json 樹. 這個 API 看起來像是  Scala 使用 NodeSeq 進行遍歷 XML 文檔一樣的:

1
2
3
4
valjson =Json.parse(jsonString)
 
valmaybeName =(json \ "user"\ name).asOpt[String]
valemails =(json \ "user"\\ "emails").map(_.as[String])

 使用 \ 來導航是不會失敗的. 當用 asOpt[T] 不存在值時會返回 None,所以這時候你需要自己來處理錯誤. 而用 as[T] 時,如果不存在值時就會報出異常.

Unmi 注:對於以上的代碼我還需要用代碼來加以說明:

01
02
03
04
05
06
07
08
09
10
      valjsonString =""" {"users":{
                 "user1":{"name":"Unmi", "email":"fantasia@sina.com"},
                 "user2":{"name":"Unmi.cc", "email":"unmi@unmi.cc"}
           }
       } """
      valjson =Json.parse(jsonString)
      valmaybeName =(json \ "users""user1""name").asOpt[String]
      println(maybeName)
      valemails =(json \ "users"\\ "email").map(_.as[String])
      println(emails)

如果試圖訪問不存在的屬性,如 (json \ "users"  \ "user1"  \ "userLaLa").asOpt[String] 時不會報錯,得到的是 None 值。而換成 (json \ "users"  \ "user1"  \ "userLaLa").as[String] 就會有異常 [RuntimeException: String expected] 。

繼續查看  println(json \ "users" \ "user1" \ "nameLaLa") 輸出的是  null

上面的 Json 是 play.api.libs.json.Json,不是 play.mvc.Json, 也不是  play.libs.Json,play.libs.Json.parse() 返回的是  JsonNode,而 play.mvc.Json 沒有 parse() 方法。

\ 和 \\ 是定義在  play.api.libs.json.Json 中的方法,\ 和  XPath 的 / 相似,直接的屬性,\\ 和 XPath 的 // 相似,子孫屬性

前面代碼兩個 println 語句的輸出是:

Unmi
List([email protected], [email protected])

對 JSON 字符串的要求還是較嚴格的,沒有 JavaScript 的 JSON 那麼隨意,屬性名一定要加上雙引號,單引號都不行。示例中的:

(json \ "user" \ name).asOpt[String]

name 代表的是前面定義的一個變量,如果是字面常量必須用雙引號框上,否則報錯:not found: value name。

轉換 Scala 值爲 Json

只要你有一個能夠被轉換爲 Json 的 Scala 類型, 那就會非常容易由 Scala 值生成 Json. 例如我們來創建一個簡單的 Json 對象:

1
valjsonNumber =Json.toJson(4)

或者創建一個 json 數組:

1
valjsonArray =Json.toJson(Seq(1234))

這兒把 Seq[Int] 轉換成 Json 數組是沒有問題的. 然而,假如 Seq 包含了不同的類型值是事情就變得複雜了:

1
valjsonArray =Json.toJson(Seq(1"Bob"34))

因爲還沒辦法把 Seq[Any] 轉換爲 Json (Any 代表着任何類型,包括 Json 無法支持的類型,不是嗎?)

Unmi 注: 報錯爲 No Json deserializer found for type Seq[Any]. Try to implement an implicit Writes or Format for this type.

一個簡單的解決方案是按照 Seq[JsValue] 來處理:

1
2
3
valjsonArray =Json.toJson(Seq(
  toJson(1), toJson("Bob"), toJson(3), toJson(4)
))

現在我們最後來看一個創建複雜 Json 對象的例子:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
val jsonObject =Json.toJson(
  Map(
    "users"-> Seq(
      toJson(
        Map(
          "name"-> toJson("Bob"),
          "age"-> toJson(31),
          "email"-> toJson("[email protected]")
        )
      ),
      toJson(
        Map(
          "name"-> toJson("Kiki"),
          "age"-> toJson(25),
          "email"-> JsNull
        )
      )
    )
  )
)

上面產生的 Json 結果是:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
{
  "users":[
    {
      "name":"Bob",
      "age":31.0,
      "email":"[email protected]"
    },
    {
      "name":"Kiki",
      "age":  25.0,
      "email":null
    }
  ]
}

序列化 Json

序列一個 JsValue 爲它的 json 字符串表示格式很簡單:

1
valjsonString:String =Json.stringify(jsValue)

其他選擇

雖然我們推薦用上面方案所描述的類型類(Unmi 注: typeclass 意思是?), 但是沒什麼能阻止用戶有需求時去使用其他的 JSON 庫.

例如, 這裏一個小片段演示了使用基 Jerkson 庫的 bundled, 反射機制,來編組原始的 scala 對象成 JSON 並進行傳輸:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
importcom.codahale.jerkson.Json._
 
valjson =generate(
  Map(
    "url"-> "http://nytimes.com",
    "attributes"-> Map(
      "name"-> "nytimes",
      "country"-> "US",
      "id"-> 25
    ),
    "links"-> List(
      "http://link1",
      "http://link2"
    )
  )
)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章