How to use Play JSON module?
首先添加JSON依赖:
libraryDependencies ++= Seq("com.typesafe.play" % "play-json_2.11" % "2.4.2")
然后这是我们需要处理的JSON用例:
{
"id": 1,
"type": "credit card",
"address": {
"address1": "Baker str 3",
"address2": "",
"city": "London",
"zipcode": "WC064"
},
"token": "u4lPaa74M"
"cvv": 112
}
这是一个支付账单,有两层嵌套,我们如何处理呢?
首先创建JSON中最深层次的模型,这是address的模型:
case class Address(address1: String, address2: Option[String], city: String, state: String, zipcode: String)
声明读(reads)写(writes)规则,用于在Scala模型和JSON之间互相转换,这个逻辑可以在Address的伴生对象中创建:
object Address { import play.api.libs.json._ implicit val addressFormats = Json.format[Address] // Json对象 def writeAddress(address: Address) = { Json.toJson(address) } def readAddress(jsonAddress: JsValue) = { jsonAddress.as[Address] } }
可以看到我们使用了Play中的Json对象,提供了对简单类型的序列化和反序列化转换,比如字符串,数字,列表等.
完成json实例中的主题部分,即Payment:
case class Payment(id: Long, pType: String, // type在Scala中是关键字,进行了修改 address: Address, // 使用Address作为嵌套类型 token: String, cvv: String) object Payment { import play.api.libs.json._ def writePayment(payment: Payment) = { JsObject(Seq( "id" -> JsNumber(payment.id), "type" -> JsString(payment.pType), "address" -> Json.toJson(payment.address), "token" -> JsString(payment.token), "cvv" -> JsString(payment.cvv) )) } def readPayment(jsonPayment: JsValue) = { val id = (jsonPayment \ "id").as[Long] val pType = (jsonPayment \ "type").as[String] val address = (jsonPayment \ "address").as[Address] val token = (jsonPayment \ "token").as[String] val cvv = (jsonPayment \ "cvv").as[String] Payment(id, pType, address, token, cvv) } }
由于Payment中使用了嵌套类型Address,这时就不能通过使用
Json.format[Payment]
来完成转换,因此通过定义其中的每个字段的转换方法,来实现读写的支持.
How to test serialisation & serialisation in Scala?
添加测试框架依赖:
name := "proectj-name"
version := "1.0"
scalaVersion := "2.11.7"
libraryDependencies ++= Seq(
"org.scalatest" % "scalatest_2.11" % "3.0.0-SNAP5" % "test",
"com.typesafe.play" % "play-json_2.11" % "2.4.2")
然后编写测试用例:
import models._
import models.Payment._
import org.scalatest._
import play.api.libs.json._
class PaymentTest extends FlatSpec with Matchers {
val address = Address("1375 Burlingame Ave.", None, "Burlingame", "California", "94010")
"Payment " should "be converted to JSON correctly " in { // 序列化测试
val payment = Payment(1, "creditCard", address, "wdweadowei3209423", "123")
val paymentJSON = writePayment(payment)
(paymentJSON \ ("id")).get should be (JsNumber(1))
(paymentJSON \ ("type")).get should be (JsString("creditCard"))
(paymentJSON \ ("address")).get should be (Json.toJson(payment.address))
(paymentJSON \ ("token")).get should be (JsString("wdweadowei3209423"))
(paymentJSON \ ("cvv")).get should be (JsString("123"))
}
it should " be deserialized correctly " in { // 反序列化测试
val paymentJSON: JsValue = JsObject(Seq(
"id" -> JsNumber(1),
"type" -> JsString("creditCard"),
"address" -> Json.toJson(address),
"token" -> JsString("wdweadowei3209423"),
"cvv" -> JsString("123")
))
val payment = readPayment(paymentJSON)
payment.id should be (1)
payment.pType should be ("creditCard")
payment.address should be (address)
payment.token should be ("wdweadowei3209423")
payment.cvv should be ("123")
}
}
更多细节可以参考官方文档.
…..