用SBT和Play进行JSON序列化

简介: 用SBT和Play进行JSON序列化 本文主要讲述如何使用Play框架的JSON模块进行JSON的序列化和反序列化。 JSON数据是非常常见的数据类型,基本上做项目就离不开JSON。

用SBT和Play进行JSON序列化

本文主要讲述如何使用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库依赖如下:

com.typesafe.playplay-json_2.112.4.3

可以下载这个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


目录
相关文章
|
1天前
|
JSON Java Linux
【探索Linux】P.30(序列化和反序列化 | JSON序列化库 [ C++ ] )
【探索Linux】P.30(序列化和反序列化 | JSON序列化库 [ C++ ] )
19 2
|
13天前
|
JSON 编译器 Go
Golang深入浅出之-结构体标签(Tags):JSON序列化与反射应用
【4月更文挑战第22天】Go语言结构体标签用于添加元信息,常用于JSON序列化和ORM框架。本文聚焦JSON序列化和反射应用,讨论了如何使用`json`标签处理敏感字段、实现`omitempty`、自定义字段名和嵌套结构体。同时,通过反射访问标签信息,但应注意反射可能带来的性能问题。正确使用结构体标签能提升代码质量和安全性。
15 0
|
2月前
|
存储 JSON JavaScript
Python中的JSON与Pickle模块:数据序列化和反序列化的利器
在Python编程中,数据的序列化和反序列化是经常遇到的操作。序列化是将数据结构或对象状态转换为可以存储或传输的格式的过程,而反序列化则是这个过程的逆操作,即将序列化的数据重新转换回原来的数据结构或对象状态。Python中的JSON和Pickle模块就是实现数据序列化和反序列化的强大工具。
|
2月前
|
JSON Java Maven
使用Jackson进行 JSON 序列化和反序列化
使用Jackson进行 JSON 序列化和反序列化
29 0
|
2月前
|
存储 JSON 安全
序列化模块pickle和json有什么区别
序列化模块pickle和json有什么区别
20 0
|
3月前
|
JSON 数据格式 C++
[序列化协议] --- JSON
[序列化协议] --- JSON
32 0
|
4月前
|
JSON Java fastjson
Java中的JSON序列化和反序列化
Java中的JSON序列化和反序列化
|
4月前
|
JSON 机器人 数据格式
阿里云RPA支持将序列化的JSON数据作为输入参数传递给机器人应用程序
【1月更文挑战第7天】【1月更文挑战第33篇】阿里云RPA支持将序列化的JSON数据作为输入参数传递给机器人应用程序
212 1
|
5月前
|
XML 存储 JSON
C# 对象存储 (轻松实现序列化 | Xml | Json | 加密 | 压缩 | 注册表 | Redis)
开发时经常会遇到需要保存配置的情况,最常见的实现方式是将对象序列化成Json,再写入文件并保存到本地磁盘。 本文将使用开源库**ApeFree.DataStore**来替换原有的对象存储过程,实现一个可以随意切换存储方式的对象存储方法。 ApeFree.DataStore是一款可配置的对象存储库,支持在不同平台/介质中对内存中的对象进行存储与还原(如本地存储、注册表存储)。支持配置序列化格式(如Json、Xml),支持配置压缩算法(如GZip、Defalte),支持配置加密算法(如AES、RSA)。
69 0
C# 对象存储 (轻松实现序列化 | Xml | Json | 加密 | 压缩 | 注册表 | Redis)
|
5月前
|
XML 存储 JSON
C# | 使用Json序列化对象时忽略只读的属性
将对象序列化成为Json字符串是一个使用频率非常高的功能。Json格式具有很高的可读性,同时相较于XML更节省空间。 在开发过程中经常会遇到需要保存配置的场景,比如将配置信息保存在配置类型的实例中,再将这个对象序列化成为Json字符串并保存。当需要加载配置时,则是读取Json格式的字符串再将其还原成配置对象。在序列化的过程中,默认会将所有公开的属性和字段都序列化进入Json字符串中,这其中也会包含只读的属性或字段,而只读的属性和字段在反序列化的过程中其实是无意义的,也就是说这一部分存储是多余的。 本文将讲解如何在执行Json序列化时,忽略掉那些只读的属性和字段。
63 0
C# | 使用Json序列化对象时忽略只读的属性