用SBT和Play进行JSON序列化
作者:chszs,未经博主允许不得转载。经许可的转载需注明作者和博客主页:http://blog.csdn.net/chszs
本文主要讲述如何使用Play框架的JSON模块进行JSON的序列化和反序列化。
JSON数据是非常常见的数据类型,基本上做项目就离不开JSON。在Scala语言中,要处理JSON有多种方法,既可以利用Java相关的JSON库(比如Jackson或GSON)进行处理,又可以使用Scala语言的JSON库。那么,在这些库Spray JSON、Play JSON、Argonaut、Jackson、Rapture中,到底应该选择哪一个呢?
我分析了Scala领域的各种JSON库,最终决定使用Play JSON库作为我的首选工具。那么,怎样使用Play框架的JSON模块来完成任务,而无需引入整个Play框架呢?我找到了这个:Play JSON
一、Play JSON模块的使用
地址: http://mvnrepository.com/artifact/com.typesafe.play/play-json_2.11
当前Play JSON库的最新版本为2.4.3版。Maven库依赖如下:
<dependency>
<groupId>com.typesafe.play</groupId>
<artifactId>play-json_2.11</artifactId>
<version>2.4.3</version>
</dependency>
可以下载这个JAR包,并加到项目类路径下。也可以使用SBT管理SCala项目,在SBT文件中添加Play JSON依赖:
name := "proectj-name"
version := "1.0"
scalaVersion := "2.11.7"
libraryDependencies ++= Seq("com.typesafe.play" % "play-json_2.11" % "2.4.3")
下面说明如何使用此库进行JSON的序列化和反序列化。
{
"id": 1,
"type": "credit card",
"address": {
"address1": "Baker str 3",
"address2": "",
"city": "London",
"zipcode": "WC064"
},
"token": "u4lPaa74M"
"cvv": 112
}
以上是账单模型的一部分——支付。它是我们进行JSON序列化和反序列化的一部分。
二、创建模型
下面为JSON数据创建对应的对象模型。
1、Address字段
case class Address(address1: String,
address2: Option[String],
city: String,
state: String,
zipcode: String)
2、声明读写规则
用于编写Scala模型到JSON的转换,以及从JSON读数据到Scala。这些逻辑可以在Address对象中进行声明:
object Address {
import play.api.libs.json._
implicit val addressFormats = Json.format[Address]
def writeAddress(address: Address) = {
Json.toJson(address)
}
def readAddress(jsonAddress: JsValue) = {
jsonAddress.as[Address]
}
}
正如你看到的,我们使用了Play的对象Json,目的是实现对象的序列化和反序列化。我仅仅简单的使用了strings、numbers、arrays和null值类型。
3、在父对象执行动作
case class Payment(id: Long,
pType: String,
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)
}
}
看上面的代码,由于type是Scala的关键字,故使用了pType作为变量代替。还有手动定义了支付对象的读写操作。
三、序列化实例
为了检查序列化是否正常工作,可以创建单元测试。在SBT文件中添加ScalaTest依赖,如下:
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")
}
}
四、总结
Play JSON库的功能足够强大,可以满足JSON相关的需求。要想了解更多内容,可以查看官方文档,见:
https://www.playframework.com/documentation/2.4.x/ScalaJson