假设使用SBT进行配置:
val json4sJackson = "org.json4s" %% "json4s-jackson" % "{latestVersion}"
解析JSON字符串
scala> import org.json4s._
scala> import org.json4s.jackson.JsonMethods._
scala> parse(""" { "numbers" : [1, 2, 3, 4] } """)
res0: org.json4s.JsonAST.JValue =
JObject(List((numbers,JArray(List(JInt(1), JInt(2), JInt(3), JInt(4))))))
scala> parse("""{"name":"Toy","price":35.35}""", useBigDecimalForDouble = true)
res1: org.json4s.package.JValue =
JObject(List((name,JString(Toy)), (price,JDecimal(35.35))))
生成JSON
有两种方式生成JSON:
import org.json4s.JsonDSL._
// or
import org.json4s.JsonDSL.WithDouble._
import org.json4s.JsonDSL.WithBigDecimal._
DSL规则
-
基本数据类型映射到
JSON
的基本数据类型
-
任何
Seq
类型映射到
JSON
的数组类型
scala> val json = List(1, 2, 3)
scala> compact(render(json))
res0: String = [1,2,3]
scala> val json = ("name" -> "joe")
scala> compact(render(json))
res1: String = {"name":"joe"}
scala> val json = ("name" -> "joe") ~ ("age" -> 35)
scala> compact(render(json))
res2: String = {"name":"joe","age":35}
scala> val json = ("name" -> "joe") ~ ("age" -> Some(35))
scala> compact(render(json))
res3: String = {"name":"joe","age":35}
scala> val json = ("name" -> "joe") ~ ("age" -> (None: Option[Int]))
scala> compact(render(json))
res4: String = {"name":"joe"}
type DslConversion = T => JValue
object JsonExample extends App {
import org.json4s._
import org.json4s.JsonDSL._
import org.json4s.jackson.JsonMethods._
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(23, List(2, 45, 34, 23, 3, 5)), Winner(54, List(52, 3, 12, 11, 18, 22)))
val lotto = Lotto(5, List(2, 45, 34, 23, 7, 5, 3), winners, None)
val json =
("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(json)))
输出结果为:
scala> JsonExample
{"lotto":{"lotto-id":5,"winning-numbers":[2,45,34,23,7,5,3],"winners":
[{"winner-id":23,"numbers":[2,45,34,23,3,5]},{"winner-id":54,"numbers":[52,3,12,11,18,22]}]}}
使用pretty可以美化输出,注意生成的字符串中没有draw-date字段:
scala> pretty(render(JsonExample.json))
"lotto":{
"lotto-id":5,
"winning-numbers":[2,45,34,23,7,5,3],
"winners":[{
"winner-id":23,
"numbers":[2,45,34,23,3,5]
"winner-id":54,
"numbers":[52,3,12,11,18,22]
合并与比较
两个JSON对象之间还可以进行合并与比较:
scala> import org.json4s._
scala> import org.json4s.jackson.JsonMethods._
scala> val lotto1 = parse("""{
"lotto":{
"lotto-id":5,
"winning-numbers":[2,45,34,23,7,5,3]
"winners":[{
"winner-id":23,
"numbers":[2,45,34,23,3,5]
}""")
scala> val lotto2 = parse("""{
"lotto":{
"winners":[{
"winner-id":54,
"numbers":[52,3,12,11,18,22]
}""")
scala> val mergedLotto = lotto1 merge lotto2
scala> pretty(render(mergedLotto))
res0: String =
"lotto":{
"lotto-id":5,
"winning-numbers":[2,45,34,23,7,5,3],
"winners":[{
"winner-id":23,
"numbers":[2,45,34,23,3,5]
"winner-id":54,
"numbers":[52,3,12,11,18,22]
scala> val Diff(changed, added, deleted) = mergedLotto diff lotto1
changed: org.json4s.JsonAST.JValue = JNothing
added: org.json4s.JsonAST.JValue = JNothing
deleted: org.json4s.JsonAST.JValue = JObject(List((lotto,JObject(List(JField(winners,
JArray(List(JObject(List((winner-id,JInt(54)), (numbers,JArray(
List(JInt(52), JInt(3), JInt(12), JInt(11), JInt(18), JInt(22))))))))))))))
查询JSON
LINQ(继承语言查询)模式
JSON中的值可以通过for生成表达式来提取。
scala> import org.json4s._
scala> import org.json4s.native.JsonMethods._
scala> val json = parse("""
{ "name": "joe",
"children": [
"name": "Mary",
"age": 5
"name": "Mazy",
"age": 3
scala> for {
JObject(child) <- json
JField("age", JInt(age)) <- child
} yield age
res0: List[BigInt] = List(5, 3)
scala> for {
JObject(child) <- json
JField("name", JString(name)) <- child
JField("age", JInt(age)) <- child
if age > 4
} yield (name, age)
res1: List[(String, BigInt)] = List((Mary,5))
XPATH + HOFs
JSON AST还支持像XPath一样进行查询:
The example json is:
"person": {
"name": "Joe",
"age": 35,
"spouse": {
"person": {
"name": "Marilyn"
"age": 33
Translated to DSL syntax:
scala> import org.json4s._
scala> import org.json4s.native.JsonMethods._
scala> import org.json4s.jackson.JsonMethods._
scala> import org.json4s.JsonDSL._
scala> val json =
("person" ->
("name" -> "Joe") ~
("age" -> 35) ~
("spouse" ->
("person" ->
("name" -> "Marilyn") ~
("age" -> 33)
scala> json \\ "spouse"
res0: org.json4s.JsonAST.JValue = JObject(List(
(person,JObject(List((name,JString(Marilyn)), (age,JInt(33)))))))
scala> compact(render(res0))
res1: String = {"person":{"name":"Marilyn","age":33}}
scala> compact(render(json \\ "name"))
res2: String = {"name":"Joe","name":"Marilyn"}
scala> compact(render((json removeField { _ == JField("name", JString("Marilyn")) }) \\ "name"))
res3: String = {"name":"Joe"}
scala> compact(render(json \ "person" \ "name"))
res4: String = "Joe"
scala> compact(render(json \ "person" \ "spouse" \ "person" \ "name"))
res5: String = "Marilyn"
scala> json findField {
case JField("name", _) => true
case _ => false
res6: Option[org.json4s.JsonAST.JValue] = Some((name,JString(Joe)))
scala> json filterField {
case JField("name", _) => true
case _ => false
res7: List[org.json4s.JsonAST.JField] = List(JField(name,JString(Joe)), JField(name,JString(Marilyn)))
scala> json transformField {
case JField("name", JString(s)) => ("NAME", JString(s.toUpperCase))
res8: org.json4s.JsonAST.JValue = JObject(List((person,JObject(List(
(NAME,JString(JOE)), (age,JInt(35)), (spouse,JObject(List(
(person,JObject(List((NAME,JString(MARILYN)), (age,JInt(33)))))))))))))
scala> json.values
res8: scala.collection.immutable.Map[String,Any] = Map(person -> Map(name -> Joe, age -> 35, spouse -> Map(person -> Map(name -> Marilyn, age -> 33))))
数组元素可以通过索引获取,还可以获取指定类型的元素:
scala> val json = parse("""
{ "name": "joe",
"children": [
"name": "Mary",
"age": 5
"name": "Mazy",
"age": 3
scala> (json \ "children")(0)
res0: org.json4s.JsonAST.JValue = JObject(List((name,JString(Mary)), (age,JInt(5))))
scala> (json \ "children")(1) \ "name"
res1: org.json4s.JsonAST.JValue = JString(Mazy)
scala> json \\ classOf[JInt]
res2: List[org.json4s.JsonAST.JInt#Values] = List(5, 3)
scala> json \ "children" \\ classOf[JString]
res3: List[org.json4s.JsonAST.JString#Values] = List(Mary, Mazy)
样式类也可以用来从JSON对象中提取值:
scala> import org.json4s._
scala> import org.json4s.jackson.JsonMethods._
scala> implicit val formats = DefaultFormats // Brings in default date formats etc.
scala> case class Child(name: String, age: Int, birthdate: Option[java.util.Date])
scala> case class Address(street: String, city: String)
scala> case class Person(name: String, address: Address, children: List[Child])
scala> val json = parse("""
{ "name": "joe",
"address": {
"street": "Bulevard",
"city": "Helsinki"
"children": [
"name": "Mary",
"age": 5,
"birthdate": "2004-09-04T18:06:22Z"
"name": "Mazy",
"age": 3
scala> json.extract[Person]
res0: Person = Person(joe,Address(Bulevard,Helsinki),List(Child(Mary,5,Some(Sat Sep 04 18:06:22 EEST 2004)), Child(Mazy,3,None)))
默认情况下构造器参数必须与json的字段匹配,如果json中的字段名在scala不合法,可以这样解决:
scala> case class Person(`first-name`: String)
scala> case class Person(firstname: String)
scala> json transformField {
case ("first-name", x) => ("firstname", x)
如果样式类具有辅助构造函数,提取函数会尽量匹配最佳的构造函数:
scala> case class Bike(make: String, price: Int) {
def this(price: Int) = this("Trek", price)
scala> parse(""" {"price":350} """).extract[Bike]
res0: Bike = Bike(Trek,350)
Scala基本类型的值可以直接从JSON中提取:
scala> (json \ "name").extract[String]
res0: String = "joe"
scala> ((json \ "children")(0) \ "birthdate").extract[Date]
res1: java.util.Date = Sat Sep 04 21:06:22 EEST 2004
日期格式可以通过重写DefaultFormats方法实现:
scala> implicit val formats = new DefaultFormats {
override def dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
JSON对象也可以转换成Map[String, _],每个字段将转换成键值对:
scala> val json = parse("""
"name": "joe",
"addresses": {
"address1": {
"street": "Bulevard",
"city": "Helsinki"
"address2": {
"street": "Soho",
"city": "London"
}""")
scala> case class PersonWithAddresses(name: String, addresses: Map[String, Address])
scala> json.extract[PersonWithAddresses]
res0: PersonWithAddresses("joe", Map("address1" -> Address("Bulevard", "Helsinki"),
"address2" -> Address("Soho", "London")))
样式类可以序列化和反序列化:
scala> import org.json4s._
scala> import org.json4s.jackson.Serialization
scala> import org.json4s.jackson.Serialization.{read, write}
scala> implicit val formats = Serialization.formats(NoTypeHints)
scala> val ser = write(Child("Mary", 5, None))
scala> read[Child](ser)
res1: Child = Child(Mary,5,None)
序列化支持:
任意深度的样式类
所有的基本类型,包括BigInt与Symbol
List,Seq,Array,Set以及Map
scala.Option
java.util.Date
Polymorphic Lists
递归类型
只含可序列化字段的类
自定义序列化函数
赠送jar包:json4s-jackson_2.12-3.5.3.jar;
赠送原API文档:json4s-jackson_2.12-3.5.3-javadoc.jar;
赠送源代码:json4s-jackson_2.12-3.5.3-sources.jar;
赠送Maven依赖信息文件:json4s-jackson_2.12-3.5.3.pom;
包含翻译后的API文档:json4s-jackson_2.12-3.5.3-javadoc-API文档-中文(简体)版.zip;
Maven坐标:org.json4s:json4s-jackson_2.12:3.5.3;
标签:json4s、jackson、中文文档、jar包、java;
使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。
人性化翻译,文档中的代码和结构保持不变,注释和说明精准翻译,请放心使用。
文章目录0 背景1 数据准备(读入数据)2 解析json文件3 组装json4 json写入到文件4.1 直接写入4.2 格式化json字符串后写入4 使用json4s
因为项目项目需要实现修改json数据后重新写入,原本解析json使用的json4s(Scala3貌似可以去使用circe-json),但是要实现替换json中的值然后重新写回到文件中实现起来方便(没有找到相对应的借口),于是去寻找了一个相对易用的包。找到了org.json,于是就用此包实现了相对应的功能。
1 数据准备(读入数据)
import com.sm.common.utils.DateUtil
import org.apache.commons.lang3.StringUtils
import org.json4s._
import org.json4s.jackson.JsonMethods._
import org.json4s.jackson.Serialization
import org.json4s.jackson.Serializa.
Json4s 全称就是Json For Scala,为Scala而生
首先上Maven依赖配置,其实Spark中自带了Json4s如果是编写Spark代码,并不需要单独引用Json4s的依赖了
<dependency>
<groupId>org.json4s</groupId>
<artifactId>json4s-jack...
At this moment there are at least 6 json libraries for scala, not counting the java json libraries. All these libraries
<groupId>org.json4s</groupId>
<artifactId>json4s-jackson_2.10</artifactId>
<version>3.2.11</version>
</dependency>
构造JSON字符串
例1implicit val f
使用 json4s库
val json4sNative = "org.json4s" %% "json4s-native" % "3.2.11"
数据类型:
sealed abstract class JValue
case object JNothing extends JValue // 'zero'..
import org.json4s._
import org.json4s.jackson.JsonMethods._
import org.json4s.JsonDSL._
val json = ("name" -> "zhangxing") ~ ("age" -> 35)
println(json.obj.toMap.get("ag
import org.json4s._
import org.json4s.JsonDSL._
import org.json4s.jackson.JsonMethods._
import org.json4s.jackson.Seria
//val parseJson: JValue = parse( """{"name":"Toy","price":35.35}""", useBigDecimalForDouble = true)
val parseJson: JValue = parse( """{"name":"Toy","price":35.35}""")
// 方法一:JString模式匹配方式
val JString(name) = (parseJson \ "name")
println(name)
//方法二:extra