总的来说在scala体系下,对于习惯了java和c#这些常规开发的人来说,无论是akka-http还是play,就处理个json序列化与反序列化真他娘够费劲的。

根据经验,Json处理是比较简单的,但是Play和akka-http的序列化让我烦恼了不少时间,所以我从自己的角度记录一下Play的JSON处理,来理解play的思维方式。

一、官方文档

代码也都是从官方文档复制后重新整理的,下面是参考的官方文档下有几篇JSON的文章

Working with Json
  1. JSON basics
  2. JSON with HTTP
  3. JSON Reads/Writes/Format Combinators
  4. JSON automated mapping
  5. 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序列化的更多相关文章

  1. C#中JSON序列化和反序列化

    有一段时间没有到博客园写技术博客了,不过每天逛逛博客园中大牛的博客还是有的,学无止境…… 最近在写些调用他人接口的程序,用到了大量的JSON.XML序列化和反序列化,今天就来总结下json的序列化和反 ...

  2. Net中JSON序列化和反序列化处理(日期时间特殊处理)

    0  缘由 笔者最近在web api端使用Json.Net进行序列化处理,而在调用端使用DataContractSerializer进行反序列化,遇到日期时间处理反序列化不成功[备注:笔者使用Net ...

  3. 在net中json序列化与反序列化 面向对象六大原则 (第一篇) 一步一步带你了解linq to Object 10分钟浅谈泛型协变与逆变

    在net中json序列化与反序列化   准备好饮料,我们一起来玩玩JSON,什么是Json:一种数据表示形式,JSON:JavaScript Object Notation对象表示法 Json语法规则 ...

  4. PHP中json序列化后中文的编码显示问题

    在接口返回数据中,我们经常会返回json或者xml格式,php的json序列化函数json_encode非常好用,但是默认会把中文编码为ASCII码(注意,很多人认为这是乱码,其实不是),尤其在调试接 ...

  5. 解决nodejs中json序列化时Date类型默认为UTC格式

    在nodejs中,json序列化时Date类型时,默认转为UTC格式. 如下图 上面只是一个例子,下面我用一个更具体化的例子来展示一个这个情况,我们在开发WEB项目中,经常用到Express组件, 我 ...

  6. 解决nodejs中json序列化时Date类型为UTC格式

    在nodejs中,json序列化时Date类型时,默认转为UTC格式. 如下图 zhupengfei@DESKTOP-HJASOE3 MINGW64 /d/MyProject/exp2 $ node ...

  7. .NET中JSON序列化(数据集转JSON)

    Json序列化和反序列化指的是:对象序列化为JSON,并可用于从 JSON 反序列化对象 在.net 3.5中已支持JSON,引用命名空间: using System.Web.Script.Seria ...

  8. Asp.Net Core中Json序列化处理整理

    一.Asp.Net Core中的Json序列化处理使用的是Newtonsoft.Json,更多参考:C# Newtonsoft.Json JsonSerializerSettings配置序列化操作,C ...

  9. 在net中json序列化与反序列化

    准备好饮料,我们一起来玩玩JSON,什么是Json:一种数据表示形式,JSON:JavaScript Object Notation对象表示法 Json语法规则: 数据在键值对中 数据由逗号分隔 花括 ...

随机推荐

  1. java Page分页显示

    //entity层实体类 import java.util.List; //分页展示 //相关属性:当前页,页大小(每页显示的条数),总页数,总条数,数据 //select * from t_user ...

  2. API手册(2017)

    本页存放内容: API手册. 少量教程 [旧的工具页面] (是一些旧的页面.不放在外面了,这里做个索引) http://www.cnblogs.com/qq21270/p/3538677.html 常 ...

  3. Python第8天

    zip() 拉链方法 max(字典) 默认比较字典的key,不同类型的数据不能比较,只要可以被for迭代即可 利用zip与max(字典)共同使用 ord() — chr()    ascii码表数字与 ...

  4. 2017-11-11 Sa Oct Is it online

    2017-11-11 Sa Oct Is it online 9:07 AM After breakfast I tried connecting to the course selection sy ...

  5. Jmeter+badboy压力测试总结

    流程:badboy导出Jmeter压测脚本 -> Jmeter进行压力测试 软件下载地址: badboy:http://www.badboy.com.au/ Jmeter:http://jmet ...

  6. 模型压缩,模型减枝,tf.nn.zero_fraction,统计0的比例,等。

    我们刚接到一个项目时,一开始并不是如何设计模型,而是去先跑一个现有的模型,看在项目需求在现有模型下面效果怎么样.当现有模型效果不错需要深入挖掘时,仅仅时跑现有模型是不够的,比如,如果你要在嵌入式里面去 ...

  7. CSS 图像高级 径向渐变

    径向渐变 径向渐变使用 radial-gradient 函数语法. 这个语法和线性渐变很类似, 可以指定渐变结束时的形状 以及它的大小. 默认来说,结束形状是一个椭圆形并且和容器的大小比例保持一致. ...

  8. tornado 基于MongoDB存储 session组件开发

    1.开发伊始 根据源码中RequestHandler类中发现__init__函数中会调用自身initialize函数,此函数中为pass,即可以围绕initialize开发一系列的组件 2.开发实现 ...

  9. window备忘录

    1.window.name属性是一个字符串,表示当前窗口的名字,只有当浏览器窗口关闭的时候,此属性才会消失. 2.window.closed属性返回一个布尔值,表示窗口是否关闭.此属性一般用来检查使用 ...

  10. kvm动态添加硬盘

    1.创建硬盘. qemu-img create -f qcow2 /data/data_root/vm-images/xxxx.qcow2 20G 2.添加硬盘 方式1.动态添加: virsh att ...