本文主要是介绍Play 2.0 中文资料 - Play JSON 库,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
Play 2.0 中文资料 - Play JSON 库
2013-01-13 — Yanbin- 使用 Json
- Play Json 库
- 处理 Json 请求
- 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 数据类型:
JsObject
JsNull
JsUndefined
JsBoolean
JsNumber
JsArray
JsString
上面的类型都继承自通用的 JSON 值类型, JsValue
.
解析 Json 字符串
你可很轻易的解析任意的 JSON 字符串为一个 JsValue
:
1 | val json : JsValue = Json.parse(jsonString) |
遍历 Json 树
一旦你得到了一个 JsValue
你就可以遍历这个 Json 树. 这个 API 看起来像是 Scala 使用 NodeSeq 进行遍历 XML 文档一样的
:
1 2 3 4 | 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]
时,如果不存在值时就会报出异常.Unmi 注:对于以上的代码我还需要用代码来加以说明:
01020304050607080910
val
jsonString
=
""
" {"
users
":{
"
user
1
":{"
name
":"
Unmi
", "
":"
fantasia
@
sina.com
"},
"
user
2
":{"
name
":"
Unmi.cc
", "
":"
unmi
@
unmi.cc
"}
}
} "
""
val
json
=
Json.parse(jsonString)
val
maybeName
=
(json \
"users"
\
"user1"
\
"name"
).asOpt[String]
println(maybeName)
val
emails
=
(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(fantasia@sina.com, unmi@unmi.cc)对 JSON 字符串的要求还是较严格的,没有 JavaScript 的 JSON 那么随意,属性名一定要加上双引号,单引号都不行。示例中的:
(json \ "user" \ name).asOpt[String]
name 代表的是前面定义的一个变量,如果是字面常量必须用双引号框上,否则报错:not found: value name。
转换 Scala 值为 Json
只要你有一个能够被转换为 Json 的 Scala 类型, 那就会非常容易由 Scala 值生成 Json. 例如我们来创建一个简单的 Json 对象:
1 | val jsonNumber = Json.toJson( 4 ) |
或者创建一个 json 数组:
1 | val jsonArray = Json.toJson(Seq( 1 , 2 , 3 , 4 )) |
这儿把 Seq[Int]
转换成 Json 数组是没有问题的. 然而,假如 Seq 包含了不同的类型值是事情就变得复杂了:
1 | val 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] 来处理
:
1 2 3 | val jsonArray = 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( "bob@gmail.com" ) ) ), 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" : "bob@gmail.com" }, { "name" : "Kiki" , "age" : 25.0 , "email" : null } ] } |
序列化 Json
序列一个 JsValue
为它的 json 字符串表示格式很简单:
1 | val jsonString : 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 | 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" ) ) ) |
这篇关于Play 2.0 中文资料 - Play JSON 库的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!