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

吴邪,小三爷,混迹于后台,大数据,人工智能领域的小菜鸟。

更多请关注

开发工具-scala处理json格式利器-json4s的更多相关文章

  1. Scala解析Json格式

    Scala解析Json格式 代码块 Scala原生包 导入包 import scala.util.parsing.json._ def main(args: Array[String]): Unit ...

  2. C#开发的WebService使用JSON格式传递数据+Ajax测试

    [C#]  WebService 使用 JSON 格式傳遞筆記 + JQuery 測試 0 2 因為一些因素,必須改寫WebService,很傳統,但是很多公司還在用.. 因為XML 的關係,不想讓他 ...

  3. 【APP接口开发】php输出json格式数据

    请一定配合使用null转空字符的方法一起使用:(_unsetNull() 和 _json() 配合使用) 在一些接口的调用中,直接查询数据库出来的字段可能为null字段,但是为了简便前端的判断,需要把 ...

  4. Android开发工具综述,开发人员必备工具

    安卓开发工具汇总.开发者必备.安卓开发过程中须要用到各种工具,作为一名安卓开发者,有木有感到亚历山大,那么多工具! 今天给大家汇总了一下安卓开发工具,安卓开发者必备利器. 1.Draw 9-Patch ...

  5. akka-grpc - 基于akka-http和akka-streams的scala gRPC开发工具

    关于grpc,在前面的scalaPB讨论里已经做了详细的介绍:google gRPC是一种全新的RPC框架,在开源前一直是google内部使用的集成工具.gRPC支持通过http/2实现protobu ...

  6. [js开源组件开发]query组件,获取url参数和form表单json格式

    query组件,获取url参数和form表单json格式 距离上次的组件[js开源组件开发]ajax分页组件一转眼过去了近二十天,或许我一周一组件的承诺有了质疑声,但其实我一直在做,只是没人看到……, ...

  7. 从零开始学android开发-Json转换利器Gson之实例

    Gson 是 Google 提供的用来在 Java 对象和 JSON 数据之间进行映射的 Java 类库.可以将一个 JSON 字符串转成一个 Java 对象,或者反过来. jar和源码下载地址: h ...

  8. 关于http接口开发中json格式数据编码问题处理

    关于http接口开发中json格式数据编码问题处理 在实际工作中,接口很多时候返回json格式,但有时返回的格式会有编码问题 假设如下接口:http://service.test.com/interf ...

  9. 写文件的工具类,输出有格式的文件(txt、json/csv)

    import java.io.BufferedWriter; import java.io.File; import java.io.FileOutputStream; import java.io. ...

随机推荐

  1. java中的IO处理和使用,API详细介绍(一)

    写在前面:本文章基本覆盖了java IO的全部内容,java新IO没有涉及,因为我想和这个分开,以突出那个的重要性,新IO哪一篇文章还没有开始写,估计很快就能和大家见面.照旧,文章依旧以例子为主,因为 ...

  2. Pytest(4)失败重跑插件pytest-rerunfailures

    安装: pip3 install pytest-rerunfailures 重新运行所有失败用例 要重新运行所有测试失败的用例,请使用--reruns命令行选项,并指定要运行测试的最大次数: $ py ...

  3. git从安装到多账户操作一套搞定(一)入门使用

    作者:良知犹存 转载授权以及围观:欢迎添加微信:Allen-Iverson-me-LYN 总述     GIT是当今热门代码管理技术,但是如此火的系统,竟然是大神林纳斯花了两周用C写出来的一个分布式版 ...

  4. Codeforces1248F. Catowice City

    题意:1e6个人每人有一只猫 每个人认识自己的猫 现给出一些关系表示一个人认识某只猫 要选出一些人和一些猫 使得每个人都不认识选出来的猫 且人+猫=n 题解:答案肯定是 一个人的集合和一个猫的集合 那 ...

  5. Codeforces Round #655 (Div. 2) B. Omkar and Last Class of Math

    题目链接:https://codeforces.com/contest/1372/problem/B 题意 给出一个正整数 $n$,找到两个正整数 $a,b$ 满足 $a+b = n$ 且 $LCM( ...

  6. Codeforces Round #625 (Div. 2, based on Technocup 2020 Final Round) C. Remove Adjacent(字符串,贪心,枚举)

    题意: 给你一个由小写字母组成的字符串,若串中两个相邻元素字典序中也相邻,移除较大字母,问最多能移除多少个字母. 思路: 从大到小依次枚举. Tips: 注意下标的处理. 以小消大: #include ...

  7. 【bzoj 2467】[中山市选2010]生成树(数论--排列组合)

    题目:有一种图形叫做五角形圈.一个五角形圈的中心有1个由n个顶点和n条边组成的圈.在中心的这个n边圈的每一条边同时也是某一个五角形的一条边,一共有n个不同的五角形.这些五角形只在五角形圈的中心的圈上有 ...

  8. LA3902 Network (树上dfs)

    题目链接:点击打开链接 题意:n台机器连成一个树状网络,其中叶节点是客户端,其他节点是服务器,目前有一台服务器s正在提供服务.让你在其他服务器上也安排同样的服务,使得每台客户端到最近服务器的距离不超过 ...

  9. Chip Factory HDU - 5536 字典树(删除节点|增加节点)

    题意: t组样例,对于每一组样例第一行输入一个n,下面在输入n个数 你需要从这n个数里面找出来三个数(设为x,y,z),找出来(x+y)^z(同样也可以(y+z)^1)的最大值 ("^&qu ...

  10. 5.PowerShell DSC核心概念之资源

    什么是资源? 资源为 DSC 配置提供构建基块. 资源公开可配置的属性,并包含本地配置管理器 (LCM) 调用以"使其如此"的 PowerShell 脚本函数. 系统内置资源 可在 ...