本文来自: http://fair-jm.iteye.com/ 转截请注明出处
一不小心 一个月没写文了 这个笔记整理也一直搁了好久...哎...
lz实习也稳定下来 现在就做做小需求啊什么的~
最近lz也办了开源力量一年的会员打算学点东西 届时会有些笔记之类的~~
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("[email protected]"), "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)) }) }