1. 为什么是 json4s
从 json4s 的官网形容
At this moment there are at least 6 json libraries for scala, not counting the java json libraries. All these libraries have a very similar AST. This project aims to provide a single AST to be used by other scala json libraries.
At this moment the approach taken to working with the AST has been taken from lift-json and the native package is in fact lift-json but outside of the lift project.
在 scala 库中,至多有 6 个 json 库,并且不包含 java 的 json 库,这些库都有着相似的形象语法树 AST,json4s 的目标就是为了应用简略的一种语法反对这些 json 库,因而说 json4s 能够说是一种 json 的标准解决,配合 scala 开发过程中极其简介的语法个性,能够轻松地实现比方 json 合并,json 的 diff 操作,能够不便地解决 jsonArray 的字符串,所以如果应用 scala,那么 json4s 肯定不能错过,在理论场景下应用 json 解决数据很常见,比方 spark 开发中解决原始 json 数据等等,开始上手可能看起来比较复杂,然而用起来你会很爽。
2.json4s 的数据结构
json4s 包含 10 个类型和一个 type 类型的对象,别离如下
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 是用来一次性匹配 json 的 key,value 对而筹备的。
3.json4s 的实际
上面来看,咱们如何来应用 json4s
<dependency>
<groupId>org.json4s</groupId>
<artifactId>json4s-native_2.11</artifactId>
<version>3.7.0-M6</version>
</dependency>
看上面的代码即可,正文写的比拟清晰,一般来说 json 的应用无外乎是字符串到对象或者对象到字符串,而字符串到对象能够用 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 办法示意从字符串到 json-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 逐层拜访
val value = (parseJson \ "name" \ "tome").extract[String]
//3.2 循环拜访
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)
// 嵌套取数组中某个字段值,并增加过滤
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 和对象的转换,[就是 json 数组]
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 转对象,[json 非 json 数组,然而每个级别要明确]
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 产生 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(","))
}
}
}
4. 留神
4.1 compact 和 render 的应用
罕用写法 compact(render(json))
, 用来把一个 json 对象转成字符串,并压缩显示,当然也能够用 prety(render(json))
4.2 序列化时候须要一个隐式对象
例如上面的
implicit val formats = Serialization.formats(NoTypeHints)
参考
更多参考官网或者非官方博客等
https://json4s.org/
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/sTVar6XXjpuM9ANFn2sx9n#xcy85CRuHfRepDBAvtvdq9
https://www.wolai.com/sTVar6XXjpuM9ANFn2sx9n#7kKK1H1h2GPZnzhiXvWG38
吴邪,小三爷,混迹于后盾,大数据,人工智能畛域的小菜鸟。
更多请关注