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 注:对于以上的代码我还需要用代码来加以说明:

01
02
03
04
05
06
07
08
09
10
       val jsonString  = "" " {" users ":{
                  " user 1 ":{" name ":" Unmi ", " email ":" fantasia @ sina.com "},
                  " user 2 ":{" name ":" Unmi.cc ", " email ":" 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([email protected], [email protected])

对 JSON 字符串的要求还是较严格的,没有 JavaScript 的 JSON 那么随意,属性名一定要加上双引号,单引号都不行。示例中的:

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

name 代表的是前面定义的一个变量,如果是字面常量必须用双引号框上,否则报错:not found: value name。

本文原始链接 http://unmi.cc/play2-0-tutorials-cn-play-json-library/, 来自 隔叶黄莺 Unmi Blog

转换 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( "[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
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)