總的來講在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]這樣的類型