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://www.shuzhiduo.com/a/vx5mbvoydn/

https://www.wolai.com/stvar6xxjpum9anfn2sx9n

https://www.wolai.com/stvar6xxjpum9anfn2sx9n

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