從json4s的官方描述
目前至少有 6 個(gè)用于 scala 的 json 庫(kù),不包括 java json 庫(kù)。所有這些庫(kù)都有一個(gè)非常相似的 AST。該項(xiàng)目旨在提供一個(gè)可供其他 scala json 庫(kù)使用的單一 AST。
目前,使用 AST 的方法是從 lift-json 中提取的,而本機(jī)包實(shí)際上是 lift-json,但在 lift 項(xiàng)目之外。
在scala庫(kù)中,至少有6個(gè)json庫(kù),并且不包括 java的json庫(kù),這些庫(kù)都有著類似的抽象語(yǔ)法樹(shù)AST,json4s的目的就是為了使用簡(jiǎn)單的一種語(yǔ)法支持這些json庫(kù),因此說(shuō)json4s可以說(shuō)是一種json的規(guī)范處理,配合scala開(kāi)發(fā)過(guò)程中極其簡(jiǎn)介的語(yǔ)法特性,可以輕松地實(shí)現(xiàn)比如json合并,json的diff操作,可以方便地處理jsonArray的字符串,所以如果使用scala,那么json4s一定不能錯(cuò)過(guò),在實(shí)際場(chǎng)景下使用json處理數(shù)據(jù)很常見(jiàn),比如spark開(kāi)發(fā)中處理原始json數(shù)據(jù)等等,開(kāi)始上手可能看起來(lái)比較復(fù)雜,但是用起來(lái)你會(huì)很爽。
json4s包括10個(gè)類型和一個(gè)type類型的對(duì)象,分別如下
case object JNothing extends JValue // 'zero' for JValue
case object JNull extends JValue
case class JString(s: String) extends JValue
case class JDouble(num: Double) extends JValue
case class JDecimal(num: BigDecimal) extends JValue
case class JInt(num: BigInt) extends JValue
case class JLong(num: Long) extends JValue
case class JBool(value: Boolean) extends JValue
case class JObject(obj: List[JField]) extends JValue
case class JArray(arr: List[JValue]) extends JValue
type JField = (String, JValue)
可以看到,他們都繼承自JValue,JValue是json4s里面類似于java的object地位,而JField是用來(lái)一次性匹配json的key,value對(duì)而準(zhǔn)備的。
下面來(lái)看,我們?nèi)绾蝸?lái)使用json4s
<dependency>
<groupId>org.json4s</groupId>
<artifactId>json4s-native_2.11</artifactId>
<version>3.7.0-M6</version>
</dependency>
看下面的代碼即可,注釋寫的比較清晰,一般來(lái)說(shuō)json的使用無(wú)外乎是字符串到對(duì)象或者對(duì)象到字符串,而字符串到對(duì)象可以用case class 也可以用原始的比如上面提到的類
package com.hoult.scala.json4s
import org.json4s._
import org.json4s.JsonDSL._
import org.json4s.native.JsonMethods._
object Demo1 {
def main(args: Array[String]): Unit = {
//parse方法表示從字符串到j(luò)son-object
val person = parse(
"""
|{"name":"Toy","price":35.35}
|""".stripMargin, useBigDecimalForDouble = true)
// 1.模式匹配提取, \表示提取
val JString(name) = (person \ "name")
println(name)
// 2.extract[String]取值
// implicit val formats = org.json4s.Formats
implicit val formats = DefaultFormats
val name2 = (person \ "name").extract[String]
val name3 = (person \ "name").extractOpt[String]
val name4 = (person \ "name").extractOrElse("")
// 3.多層嵌套取值
val parseJson: JValue = parse(
"""
|{"name":{"tome":"new"},"price":35.35}
|""".stripMargin, useBigDecimalForDouble = true)
//3.1 逐層訪問(wèn)
val value = (parseJson \ "name" \ "tome").extract[String]
//3.2 循環(huán)訪問(wèn)
val value2 = (parseJson \\ "tome")
println(value2)
//4.嵌套json串解析
val json = parse(
"""
{ "name": "joe",
"children": [
{
"name": "Mary",
"age": 20
},
{
"name": "Mazy",
"age": 10
}
]
}
""")
// println(json \ "children")
//模式匹配
for (JArray(child) <- json) println(child)
//提取object 下 某字段的值
val ages = for {
JObject(child) <- json
JField("age", JInt(age)) <- child
} yield age
println(ages)
// 嵌套取數(shù)組中某個(gè)字段值,并添加過(guò)濾
val nameAges = for {
JObject(child) <- json
JField("name", JString(name)) <- child
JField("age", JInt(age)) <- child
if age > 10
} yield (name, age)
println(nameAges)
// 5.json和對(duì)象的轉(zhuǎn)換,[就是json數(shù)組]
case class ClassA(a: Int, b: Int)
val json2: String = """[{"a":1,"b":2},{"a":1,"b":2}]"""
val bb: List[ClassA] = parse(json2).extract[List[ClassA]]
println(bb)
// 6.json轉(zhuǎn)對(duì)象,[json 非json數(shù)組,但是每個(gè)級(jí)別要明確]
case class ClassC(a: Int, b: Int)
case class ClassB(c: List[ClassC])
val json3: String = """{"c":[{"a":1,"b":2},{"a":1,"b":2}]}"""
val cc: ClassB = parse(json3).extract[ClassB]
println(cc)
// 7.使用org.json4s產(chǎn)生json字符串
// import org.json4s.JsonDSL._
val json1 = List(1, 2, 3)
val jsonMap = ("name" -> "joe")
val jsonUnion = ("name" -> "joe") ~ ("age" -> 10)
val jsonOpt = ("name" -> "joe") ~ ("age" -> Some(1))
val jsonOpt2 = ("name" -> "joe") ~ ("age" -> (None: Option[Int]))
case class Winner(id: Long, numbers: List[Int])
case class Lotto(id: Long, winningNumbers: List[Int], winners: List[Winner], drawDate: Option[java.util.Date])
val winners = List(Winner(10, List(1, 2, 5)), Winner(11, List(1, 2, 0)))
val lotto = Lotto(11, List(1, 2, 5), winners, None)
val jsonCase =
("lotto" ->
("lotto-id" -> lotto.id) ~
("winning-numbers" -> lotto.winningNumbers) ~
("draw-date" -> lotto.drawDate.map(_.toString)) ~
("winners" ->
lotto.winners.map { w =>
(("winner-id" -> w.id) ~
("numbers" -> w.numbers))}))
println(compact(render(json1)))
println(compact(render(jsonMap)))
println(compact(render(jsonUnion)))
println(compact(render(jsonOpt)))
println(compact(render(jsonOpt2)))
println(compact(render(jsonCase)))
// 8.json格式化
println(pretty(render(jsonCase)))
// 9.合并字符串
val lotto1 = parse("""{
"lotto":{
"lotto-id": 1,
"winning-numbers":[7,8,9],
"winners":[{
"winner-id": 1,
"numbers":[7,8,9]
}]
}
}""")
val lotto2 = parse("""{
"lotto":{
"winners":[{
"winner-id": 2,
"numbers":[1,23,5]
}]
}
}""")
val mergedLotto = lotto1 merge lotto2
// println(pretty(render(mergedLotto)))
// 10.字符串尋找差異
val Diff(changed, added, deleted) = mergedLotto diff lotto1
println(changed)
println(added)
println(deleted)
val json10 = parse(
"""
""")
println("********8")
println(json10)
for (JObject(j) <- json10) println(j)
println("********11")
// 11.遍歷json,使用for
// key1 values key1_vk1:v1 ....
val str = "{\"tag_name\":\"t_transaction_again_day\",\"tag_distribute_json\":\"{\\\"1\\\":\\\"0.0011231395\\\",\\\"0\\\":\\\"0.9988768605\\\"}\"}"
val valueJson = parse(str) \ "tag_distribute_json"
println(valueJson)
for {
JString(obj) <- valueJson
JObject(dlist) <- parse(obj)
(key, JString(value))<- dlist
} {
println(key + "::" + value)
// val kvList = for (JObject(key, value) <- parse(obj)) yield (key, value)
// println("obj : " + kvList.mkString(","))
}
}
}
常用寫法compact(render(json))
,用來(lái)把一個(gè)json對(duì)象轉(zhuǎn)成字符串,并壓縮顯示,當(dāng)然也可以用prety(render(json))
例如下面的
implicit val formats = Serialization.formats(NoTypeHints)
更多參考官網(wǎng)或者非官方博客等
https://github.com/json4s/json4s/tree/v.3.2.0_scala2.10
https://www.cnblogs.com/yyy-blog/p/11819302.html
https://www.shuzhiduo.com/A/Vx5MBVOYdN/
https://segmentfault.com/a/1190000007302496
https://www.coder.work/article/6786418
https://www.wolai.com/sTVar6XXjp uM9ANFn2sx9n#xcy85CRuHfRepDBAvtvdq9
https://www.wolai.com/sTVar6XXjpuM9ANFn2sx9n#7kKK1H1h2GPZnzhiXvWG38
吳邪,小三爺,混跡于后臺(tái),大數(shù)據(jù),人工智能領(lǐng)域的小菜鳥(niǎo)。
聯(lián)系客服