总的来讲在scala体系下,对于习惯了java和c#这些常规开发的人来讲,不管是akka-http仍是play,就处理个json序列化与反序列化真他娘够费劲的。java
根据经验,Json处理是比较简单的,可是Play和akka-http的序列化让我烦恼了很多时间,因此我从本身的角度记录一下Play的JSON处理,来理解play的思惟方式。git
代码也都是从官方文档复制后从新整理的,下面是参考的官方文档下有几篇JSON的文章github
1.本例中使用的实体类web
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.序列化例子json
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.解释c#
通常的json序列化比较简单,有一个相似JsonManager的管理类,提供serialize(object obj)与deserialize<T>(string json)这样方法,通常不须要开发者作太多的工做,比较简单,也是基于这种认识,因此对play的json处理方式就会困惑。api
缘由是scala和akka系列声称本身是可伸缩的框架,面向大数据领域,他认为传统的方式是比较重的oo方式,而大数据的处理主要是批量处理数据,因此可能只是对批量数据的个别字段作简单的运算便可,不须要沉重的OOM,看他原文的描述:app
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?框架
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:less
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是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?
4、直接用Jackson进行序列化
这篇文章介绍了直接SCALA使用Jackson进行JSON序列化
可是也不是那么完美,集合只能用java的集合,bean不能使用Option[Double]这样的类型