Play中JSON序列化
总的来说在scala体系下,对于习惯了java和c#这些常规开发的人来说,无论是akka-http还是play,就处理个json序列化与反序列化真他娘够费劲的。
根据经验,Json处理是比较简单的,但是Play和akka-http的序列化让我烦恼了不少时间,所以我从自己的角度记录一下Play的JSON处理,来理解play的思维方式。
一、官方文档
代码也都是从官方文档复制后重新整理的,下面是参考的官方文档下有几篇JSON的文章
Working with Json
- JSON basics
- JSON with HTTP
- JSON Reads/Writes/Format Combinators
- JSON automated mapping
- JSON Transformers
二、实体序列化例子
1.本例中使用的实体类
package serialize case class Location(lat: Double, long: Double)
case class Resident(name: String, age: Int, role: Option[String])
case class Place(name: String, location: Location, residents: Seq[Resident])
2.序列化例子
import play.api.libs.json._
import play.api.libs.functional.syntax._
import serialize.{Location, Place, Resident} object PlayJsonTest{ def main(args:Array[String]):Unit={ implicit val locationReads = Json.reads[Location]
implicit val residentReads = Json.reads[Resident]
implicit val placeReads = Json.reads[Place] val json: JsValue = Json.parse("""
{
"name" : "Watership Down",
"location" : {
"lat" : 51.235685,
"long" : -1.309197
},
"residents" : [ {
"name" : "Fiver",
"age" : 4,
"role" : null
}, {
"name" : "Bigwig",
"age" : 6,
"role" : "Owsla"
} ]
}
""") val result: JsResult[Place] = Json.fromJson[Place](json) result match {
case JsSuccess(r: Place, path: JsPath) => println("Name: " + r.name)
case e: JsError => println("Errors: " + JsError.toJson(e).toString())
}
}
}
3.解释
一般的json序列化比较简单,有一个类似JsonManager的管理类,提供serialize(object obj)与deserialize<T>(string json)这样方法,一般不需要开发者做太多的工作,比较简单,也是基于这种认识,所以对play的json处理方式就会困惑。
原因是scala和akka系列声称自己是可伸缩的框架,面向大数据领域,他认为传统的方式是比较重的oo方式,而大数据的处理主要是批量处理数据,所以可能只是对批量数据的个别字段做简单的运算即可,不需要沉重的OOM,看他原文的描述:
Are we doomed to convert JSON to OO?
For a few years now, in almost all web frameworks (except recent JavaScript server side stuff maybe in which JSON is the default data structure), we have been used to get JSON from network and convert JSON (or even POST/GET data) into OO structures such as classes (or case classes in Scala). Why?
- For a good reason : OO structures are “language-native” and allows manipulating data with respect to your business logic in a seamless way while ensuring isolation of business logic from web layers.
- For a more questionable reason : ORM frameworks talk to DB only with OO structures and we have (kind of) convinced ourselves that it was impossible to do else… with the well-known good & bad features of ORMs… (not here to criticize those stuff)
Is OO conversion really the default use case?
In many cases, you don’t really need to perform any real business logic with data but validating/transforming before storing or after extracting. Let’s take the CRUD case:
- You just get the data from the network, validate them a bit and insert/update into DB.
- In the other way, you just retrieve data from DB and send them outside.
So, generally, for CRUD ops, you convert JSON into a OO structure just because the frameworks are only able to speak OO.
I don’t say or pretend you shouldn’t use JSON to OO conversion but maybe this is not the most common case and we should keep conversion to OO only when we have real business logic to fulfill.
4.总结
先要知道play的json的关注点,以及他的思维方式,对于这种思维方式的好与坏,其实也无所谓。
三、json4s
json4s是scala下使用OO方式可以很接近的方法,他也提供了一些play.json关注的类xpath查询的这种功能,参见json4s的github
在akka-http下实在是无法忍受从1个到24个类属性序列化的这种方式,所以可以是一个比较好的选择
json4s的sbt引用
"org.json4s" %% "json4s-jackson" % "3.6.2",
本例使用的实体还是上文的实体,对应的序列化代码为:
package org.netsharp.jsonoom import java.text.SimpleDateFormat import org.json4s._
import org.json4s.jackson.JsonMethods._
import org.json4s.jackson.Serialization object Json4sDemo { def main(args:Array[String]):Unit={ var json:String = """
{
"name" : "Watership Down",
"location" : {
"lat" : 51.235685,
"long" : -1.309197
},
"residents" : [ {
"name" : "Fiver",
"age" : 4,
"role" : null
}, {
"name" : "Bigwig",
"age" : 6,
"role" : "Owsla"
} ]
}
"""; // implicit val formats = Serialization.formats(NoTypeHints)
implicit val formats = new DefaultFormats {
override def dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
} var place:Place = Serialization.read[Place](json)
json = Serialization.write(place) println(json) //另外一种序列化接口
place = parse(json).extract[Place] }
}
总的来说,json4s和play.json思路类似,他们都是基于jackson的序列化
你说是不是play.json抄袭了json4s?
四、直接用Jackson进行序列化
这篇文章介绍了直接SCALA使用Jackson进行JSON序列化
但是也不是那么完美,集合只能用java的集合,bean不能使用Option[Double]这样的类型
Play中JSON序列化的更多相关文章
- C#中JSON序列化和反序列化
有一段时间没有到博客园写技术博客了,不过每天逛逛博客园中大牛的博客还是有的,学无止境…… 最近在写些调用他人接口的程序,用到了大量的JSON.XML序列化和反序列化,今天就来总结下json的序列化和反 ...
- Net中JSON序列化和反序列化处理(日期时间特殊处理)
0 缘由 笔者最近在web api端使用Json.Net进行序列化处理,而在调用端使用DataContractSerializer进行反序列化,遇到日期时间处理反序列化不成功[备注:笔者使用Net ...
- 在net中json序列化与反序列化 面向对象六大原则 (第一篇) 一步一步带你了解linq to Object 10分钟浅谈泛型协变与逆变
在net中json序列化与反序列化 准备好饮料,我们一起来玩玩JSON,什么是Json:一种数据表示形式,JSON:JavaScript Object Notation对象表示法 Json语法规则 ...
- PHP中json序列化后中文的编码显示问题
在接口返回数据中,我们经常会返回json或者xml格式,php的json序列化函数json_encode非常好用,但是默认会把中文编码为ASCII码(注意,很多人认为这是乱码,其实不是),尤其在调试接 ...
- 解决nodejs中json序列化时Date类型默认为UTC格式
在nodejs中,json序列化时Date类型时,默认转为UTC格式. 如下图 上面只是一个例子,下面我用一个更具体化的例子来展示一个这个情况,我们在开发WEB项目中,经常用到Express组件, 我 ...
- 解决nodejs中json序列化时Date类型为UTC格式
在nodejs中,json序列化时Date类型时,默认转为UTC格式. 如下图 zhupengfei@DESKTOP-HJASOE3 MINGW64 /d/MyProject/exp2 $ node ...
- .NET中JSON序列化(数据集转JSON)
Json序列化和反序列化指的是:对象序列化为JSON,并可用于从 JSON 反序列化对象 在.net 3.5中已支持JSON,引用命名空间: using System.Web.Script.Seria ...
- Asp.Net Core中Json序列化处理整理
一.Asp.Net Core中的Json序列化处理使用的是Newtonsoft.Json,更多参考:C# Newtonsoft.Json JsonSerializerSettings配置序列化操作,C ...
- 在net中json序列化与反序列化
准备好饮料,我们一起来玩玩JSON,什么是Json:一种数据表示形式,JSON:JavaScript Object Notation对象表示法 Json语法规则: 数据在键值对中 数据由逗号分隔 花括 ...
随机推荐
- 一些最常见的SNMP的OID自动翻译成zabbix数字进行表示(华为9306)
转载自:https://blog.51cto.com/davidbj/1173954 随着Zabbix 2.0版本的发布,很多企业开始用zabbix来代替之前的Nagio.Cacti等其它监控软件.至 ...
- 网络协议,socket模块
"""网络通讯要素:1.物理介质2.通讯协议 osi五层模型 应用层 传输层 网络层 数据链路层 物理层 物理层能传输010101二进制单纯的二进制是没有意义的,必须得知 ...
- 9Linux_LVM_iptables
LVM 创建物理卷 卷组 逻辑卷 格式化 挂载 扩容 缩小 快照 删除逻辑卷
- python docker 多进程提供 稳定tensorflow gpu 线上服务
尝试了太多的python多进程的服务,在tensorflow 的线上GPU服务中总是不理想.tensorlfow serving docker服务这些也有些不便. 今天抽空给大家分享一个成功的经验.失 ...
- DRF框架之 用户角色权限与访问频率的权限设置
1. 简单演示,创建一个models的数据库表 class User(models.Model): name=models.CharField(max_length=32) pwd=models.Ch ...
- Java学习--变量
参考 http://www.runoob.com/java/java-variable-types.html java变量使用前 java中的所有变量在使用前必须声明并且初始化 类变量和实例变量会默 ...
- linux 之用户管理
用户的家目录 普通用户:/home/用户名/,所有者和所属组都是此用户,权限是700 超级用户:/root/,所有者和所属组都是root用户,权限是550 用户邮箱目录 /var/spool/mail ...
- java发送post请求,使用multipart/form-data的方式传递参数,可实现服务器间文件上传功能(转)
废话少说,直接上代码: /** * 测试上传图片 * */ public static void testUploadImage(){ String url = "http://xxxtes ...
- Mha-Atlas-MySQL高可用方案实践(二)
六,配置VIP漂移 主机名 IP地址(NAT) 漂移VIP 描述 mysql-db01 eth0:192.168.0.51 VIP:192.168.0.60 系统:CentOS6.5(6.x都可以) ...
- python之字典及其方法---整理集
字典 特点: 使用逗号分隔的key:value形式: 使用大括号括起来: key-value的键值对中,value部分可以是任意类型: 列表.字典不能做为字典的key: 字典是无序的,哪个key-va ...