服务器之家

服务器之家 > 正文

Java开发工具-scala处理json格式利器-json4s详解

时间:2021-08-15 16:23     来源/作者:SuperFox

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类型的对象,分别如下

?
1
2
3
4
5
6
7
8
9
10
11
12
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

?
1
2
3
4
5
<dependency>
 <groupId>org.json4s</groupId>
 <artifactId>json4s-native_2.11</artifactId>
 <version>3.7.0-M6</version>
</dependency>

看下面的代码即可,注释写的比较清晰,一般来说json的使用无外乎是字符串到对象或者对象到字符串,而字符串到对象可以用case class 也可以用原始的比如上面提到的类

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
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 序列化时候需要一个隐式对象

例如下面的

?
1
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

https://www.wolai.com/sTVar6XXjpuM9ANFn2sx9n

到此这篇关于开发工具-scala处理json格式利器-json4s的文章就介绍到这了,更多相关scala处理json格式利器-json4s内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://www.cnblogs.com/hulichao/p/14435161.html

标签:

相关文章

热门资讯

yue是什么意思 网络流行语yue了是什么梗
yue是什么意思 网络流行语yue了是什么梗 2020-10-11
2020微信伤感网名听哭了 让对方看到心疼的伤感网名大全
2020微信伤感网名听哭了 让对方看到心疼的伤感网名大全 2019-12-26
背刺什么意思 网络词语背刺是什么梗
背刺什么意思 网络词语背刺是什么梗 2020-05-22
苹果12mini价格表官网报价 iPhone12mini全版本价格汇总
苹果12mini价格表官网报价 iPhone12mini全版本价格汇总 2020-11-13
2021德云社封箱演出完整版 2021年德云社封箱演出在线看
2021德云社封箱演出完整版 2021年德云社封箱演出在线看 2021-03-15
返回顶部