Play 2.0 中文资料 - Play JSON 库
概述
推荐的处理 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 数据类型:JsObjectJsNullJsUndefinedJsBooleanJsNumberJsArrayJsString
上面的类型都继承自通用的 JSON 值类型,
JsValue.解析 Json 字符串
你可很轻易的解析任意的 JSON 字符串为一个
JsValue:1val json: JsValue = Json.parse(jsonString)遍历 Json 树
一旦你得到了一个
JsValue 你就可以遍历这个 Json 树. 这个 API 看起来像是 Scala 使用 NodeSeq 进行遍历 XML 文档一样的:1val json = Json.parse(jsonString)
2
3val maybeName = (json \ "user" \ name).asOpt[String]
4val emails = (json \ "user" \\ "emails").map(_.as[String])注 使用 \ 来导航是不会失败的. 当用转换 Scala 值为 JsonasOpt[T]不存在值时会返回None,所以这时候你需要自己来处理错误. 而用as[T]时,如果不存在值时就会报出异常. Unmi 注:对于以上的代码我还需要用代码来加以说明:如果试图访问不存在的属性,如 (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 语句的输出是: Unmi1val jsonString = """ {"users":{ 2 "user1":{"name":"Unmi", "email":"fantasia@sina.com"}, 3 "user2":{"name":"Unmi.cc", "email":"unmi@unmi.cc"} 4 } 5 } """ 6val json = Json.parse(jsonString) 7val maybeName = (json \ "users" \ "user1" \ "name").asOpt[String] 8println(maybeName) 9val emails = (json \ "users" \\ "email").map(_.as[String]) 10println(emails)
List(fantasia@sina.com, unmi@unmi.cc) 对 JSON 字符串的要求还是较严格的,没有 JavaScript 的 JSON 那么随意,属性名一定要加上双引号,单引号都不行。示例中的: (json \ "user" \ name).asOpt[String] name 代表的是前面定义的一个变量,如果是字面常量必须用双引号框上,否则报错:not found: value name。
只要你有一个能够被转换为 Json 的 Scala 类型, 那就会非常容易由 Scala 值生成 Json. 例如我们来创建一个简单的 Json 对象:
1val jsonNumber = Json.toJson(4)或者创建一个 json 数组:
1val jsonArray = Json.toJson(Seq(1, 2, 3, 4))这儿把
Seq[Int] 转换成 Json 数组是没有问题的. 然而,假如 Seq 包含了不同的类型值是事情就变得复杂了:1val jsonArray = Json.toJson(Seq(1, "Bob", 3, 4))因为还没办法把
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] 来处理:1val jsonArray = Json.toJson(Seq(
2 toJson(1), toJson("Bob"), toJson(3), toJson(4)
3))现在我们最后来看一个创建复杂 Json 对象的例子:
1val jsonObject = Json.toJson(
2 Map(
3 "users" -> Seq(
4 toJson(
5 Map(
6 "name" -> toJson("Bob"),
7 "age" -> toJson(31),
8 "email" -> toJson("bob@gmail.com")
9 )
10 ),
11 toJson(
12 Map(
13 "name" -> toJson("Kiki"),
14 "age" -> toJson(25),
15 "email" -> JsNull
16 )
17 )
18 )
19 )
20)上面产生的 Json 结果是:
1{
2 "users":[
3 {
4 "name": "Bob",
5 "age": 31.0,
6 "email": "bob@gmail.com"
7 },
8 {
9 "name": "Kiki",
10 "age": 25.0,
11 "email": null
12 }
13 ]
14}序列化 Json
序列一个
JsValue 为它的 json 字符串表示格式很简单:1val jsonString: String = Json.stringify(jsValue)其他选择
虽然我们推荐用上面方案所描述的类型类(Unmi 注: typeclass 意思是?), 但是没什么能阻止用户有需求时去使用其他的 JSON 库.
例如, 这里一个小片段演示了使用基 Jerkson 库的 bundled, 反射机制,来编组原始的 scala 对象成 JSON 并进行传输:
1import com.codahale.jerkson.Json._
2
3val json = generate(
4 Map(
5 "url"-> "http://nytimes.com",
6 "attributes" -> Map(
7 "name" -> "nytimes",
8 "country" -> "US",
9 "id" -> 25
10 ),
11 "links" -> List(
12 "http://link1",
13 "http://link2"
14 )
15 )
16)[版权声明]
本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。