一個scala常用的json工具
java里面的fastjson,gson,和Jackson是我最熟悉的json序列化框架颤专,用起來沒什么問題,接觸了scala之后喂窟,我看到很多項目使用sprayjson,尤其是akka相關(guān)的項目毅人,使用特別多铣耘,因為剛接觸scala肋殴,它的伴生對象和implicit隱式語義會讓新手使用spray json的時候,有一點點困惑坦弟。
json序列化的流程
簡單說就是json字符串和對象的互轉(zhuǎn)护锤,java里面的對象一般是指bean,有的也叫pojo酿傍,scala里面一般指case class的對象烙懦。
還有很多框架不提供到bean的轉(zhuǎn)換,而是直接轉(zhuǎn)成JsonObject和JsonArray對象赤炒,有的同時支持氯析,比如fastJson,spray json 同樣也都支持莺褒,基礎(chǔ)類叫做JsonValue掩缓,具體的還有JSNumber、JSString遵岩、JSBoolean等更詳細的數(shù)據(jù)類型你辣,原理其實跟其它java的json框架沒有太大的區(qū)別
具體用的時候巡通,spray json是這樣的:導(dǎo)入
import spray.json._
,
一個json串舍哄,調(diào)用parseJson
方法
一個scala對象調(diào)用toJson
方法
都可以轉(zhuǎn)化為一個spray json的語法樹對象
這個語法樹對象可以打印成json字符串宴凉,也可以轉(zhuǎn)化為一個scala對象
轉(zhuǎn)為json字符串:
prettyPrint // or .compactPrint
轉(zhuǎn)為對象val myObject = jsonAst.convertTo[MyObjectType]
https://github.com/spray/spray-json
具體的參考這個文檔即可
調(diào)用方式都是死的,無非是convertTo表悬,parseJson弥锄,toJson,但是具體怎么轉(zhuǎn)蟆沫,是需要協(xié)議的籽暇,框架本身內(nèi)置了一大堆協(xié)議,用于scala基礎(chǔ)對象類型的轉(zhuǎn)化饥追,而我們自定義的case class或者class需要我們自己實現(xiàn)轉(zhuǎn)化的方式图仓,這個是我們需要編碼的地方。
兩種比較常用的方式
1但绕、JsonProtocol
對于沒有顯示聲明伴生對象的情況救崔,sprayjson給你準(zhǔn)備了很多 jsonFormatX,x對應(yīng)你的case class參數(shù)個數(shù)捏顺,比如
case class Color(name: String, red: Int, green: Int, blue: Int)
object MyJsonProtocol extends DefaultJsonProtocol {
implicit val colorFormat = jsonFormat4(Color)
}
如果有22個參數(shù)六孵,那就是jsonFormat22,這些框架提供的jsonFormatX使用的話幅骄,需要導(dǎo)入spray.json.DefaultJsonProtocol_,這也是scala隱式的特點
如果顯示聲明了伴生對象劫窒,那么就不能直接jsonFormat4(Color)
這樣寫了,上面這個例子里拆座,如果聲明了Color伴生對象主巍,那么jsonFormat4(Color)
里的Color會被理解成Color對象,這時候需要我們提供伴生對象的apply方法挪凑,要寫成這樣
case class Color(name: String, red: Int, green: Int, blue: Int)
object Color
object MyJsonProtocol extends DefaultJsonProtocol {
implicit val colorFormat = jsonFormat4(Color.apply)
}
2孕索、普通 class的序列化
普通class即非case class的情況,多數(shù)用到RootJsonFormat躏碳,這時候需要我們重寫read,write方法搞旭,即JSValue和class對象的轉(zhuǎn)換關(guān)系
例如:
class Color(val name: String, val red: Int, val green: Int, val blue: Int)
object MyJsonProtocol extends DefaultJsonProtocol {
implicit object ColorJsonFormat extends RootJsonFormat[Color] {
def write(c: Color) =
JsArray(JsString(c.name), JsNumber(c.red), JsNumber(c.green), JsNumber(c.blue))
def read(value: JsValue) = value match {
case JsArray(Vector(JsString(name), JsNumber(red), JsNumber(green), JsNumber(blue))) =>
new Color(name, red.toInt, green.toInt, blue.toInt)
case _ => deserializationError("Color expected")
}
}
}
import MyJsonProtocol._
val json = new Color("CadetBlue", 95, 158, 160).toJson
val color = json.convertTo[Color]
更復(fù)雜的用法,后面陸續(xù)補充