JSON处理主要用到:
play.api.libs.json
包中的对象和类
JsValue及子类:
■ JsString
■ JsNumber Int,Long,Double 有隐式转换
■ JsBoolean
■ JsObject Seq[(String,JsValue)]
■ JsArray Seq[JsValue]做参数
■ JsNull
以上这些代表了json的组成元素 可以直接用以上的类来构建JSON
Json对象提供了一些方便的工具
toJson方法
- val product = Json.obj(
- "name" -> JsString("Blue Paper clips"),
- "ean" -> JsString("12345432123"),
- "description" -> JsString("Big box of paper clips"),
- "pieces" -> JsNumber(500),
- "manufacturer" -> Json.obj(
- "name" -> JsString("Paperclipfactory Inc."),
- "contact_details" -> Json.obj(
- "email" -> JsString("contact@paperclipfactory.example.com"),
- "fax" -> JsNull,
- "phone" -> JsString("+12345654321")
- )
- ),
- "tags" -> Json.arr(
- JsString("paperclip"),
- JsString("coated")
- ),
- "active" -> JsBoolean(true)
- )
如果想将JsValue(及子类对象)转化为String
可以用:
- val productJsonString = Json.stringify(product) //用JsValue的toString方法也可以 会调用这个方法
对象到JSON:
toJson方法可用于 String Option[Int] 以及 Map[String,String]
要实现其他类别的 可以继承Writes覆写writes方法
对于case class 也可以用Json提供的方法在运行时生成相应的Writes:
- implicit val productWrites = Json.writes[Product]
也可以用Path
JSON到Object:
前者是Writes 现在是Reads
用JsValue的as方法 Reads由JsPath生成:
此外也可以使用asOpt 那么返回的将是一个Option
- implicit val reads:Reads[Product] = (
- (JsPath \ "ean").read[Long] and
- (JsPath \ "name").read[String] and
- (JsPath \ "description").read[String]
- )(Product.apply _)
(用JsPath也可以生成Writes 把read换成write即可)
从String->JsValue 用Json.parse
在request中也可以用request.body.asJson 得到一个Option[JsValue]
如果Action只处理JSON的数据 可以写成:
- def postProduct2() = Action(parse.json) { request =>
- val jsValue = request.body
- // Do something with the JSON
- }
如果content-type不符合(text/json 或者 application/json)就会直接返回400 Bad Request 可以使用parse.tolerantJson如果没有设置content-type的话
用jsValue的validate方法可以检查是否可以转换(用隐式的Reads作为参数):
- val age = jsValue.validate[Int] // == JsError
- val name = jsValue.validate[String] // == JsSuccess(Johnny,)
- import Json._
- val json: JsValue = toJson(Map(
- "name" -> toJson("Johnny"),
- "age" -> toJson(42),
- "tags" -> toJson(List("constructor", "builder")),
- "company" -> toJson(Map(
- "name" -> toJson("Constructors Inc.")))))
处理:
- val name = (json \ "name").as[String]
- val age = (json \ "age").asOpt[Int]
- val companyName = (json \ "company" \ "name").as[String]
- val firstTag = (json \ "tags")(0).as[String]
- val allNames = (json \\ "name").map(_.as[String])
如果不符合 不会抛出异常 会返回JsUndefined(也是JsValue的子类) 或者也可以用asOpt返回Option
可以用模式匹配处理:
- (json \ "name") match {
- case JsString(name) => println(name)
- case JsUndefined(error) => println(error)
- case _ => println("Invalid type!")
- }
Format
Reads和Writes可以合并 用Format
Format[T]继承自Reads[T]和Writes[T]
然后使用JsPath的format和formatNullable方法:
- import play.api.libs.json._
- import play.api.libs.functional.syntax._
- implicit val productFormat = (
- (JsPath \ "name").format[String] and
- (JsPath \ "description").formatNullable[String] and
- (JsPath \ "purchase_price").format[BigDecimal] and
- (JsPath \ "selling_price").format[BigDecimal]
- )(PricedProduct.apply, unlift(PricedProduct.unapply))
或者用现有的Reads和Writes:
- implicit val productFormat = Format(productReads, productWrites)
对于case class 也可以用运行时生成的方式:
- implicit val productFormat = Json.format[PricedProduct]
这种方式是用scala macro生成的 类型安全 对应的还有Json.reads()和Json.writes
检查
检查: 可以在reads中写规则 这些规则来自:play.api.libs.json.ConstraintReads
- implicit val companyReads: Reads[Company] = (
- (JsPath \ "name").read[String] and
- (JsPath \ "contact_details").read(
- (
- (JsPath \ "email").readNullable[String](email) and
- (JsPath \ "fax").readNullable[String](minLength[String](10)) and
- (JsPath \ "phone").readNullable[String](minLength[String](10))
- )(Contact.apply _))
- )(Company.apply _)
验证用JsValue的validate方法 和Form的bindFromRequest类似:
- def save = Action(parse.json) { implicit request =>
- val json = request.body
- json.validate[Product].fold(
- valid = { product =>
- Product.save(product)
- Ok("Saved")
- },
- invalid = {
- errors => BadRequest(JsError.toFlatJson(errors))
- })
- }