scala中json4s 使用详解

预备知识

json4s的数据结构AST (Abstract Syntax Tree)。

sealed abstract class JValue
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 JBool(value: Boolean) extends JValue
case class JObject(obj: List[JField]) extends JValue
case class JArray(arr: List[JValue]) extends JValuetype JField = (String, JValue)

我们可以通过 json4s 对json所做的操作如下图所示,中间为 Json AST (简单理解就是一个用JValue表示的 JSON)。
在这里插入图片描述

另外,org.json4s下定义了很多scala原生数据转JValue的隐式转换(即多数操作下可以把原生数据当做JValue直接使用)
在这里插入图片描述
但是注意:Tuple不能自动转为JValue,在需要转换的时候,render先转一下,如:json merge render("height",175)

一、 创建json对象

{"name":"luca", "id": "1q2w3e4r5t", "age": 26, "url":"http://www.nosqlnocry.wordpress.com"}

方式1:parse函数

// parse from string example,得到的是JValue对象
var json = parse("""{"name":"luca", "id": "1q2w3e4r5t", "age": 26, "url":"http://www.nosqlnocry.wordpress.com"}""")

方式2:dsl创建

org.json4s中定义了从tuple到JValue的操作符

// DSL example,是JObject对象
var json = ("name","luca") ~ ("id","1q2w3e4r5t") ~ ("age",26) ~ ("url","http://www.nosqlnocry.wordpress.com")
// tuples can be defined also like this: ("id" -> "1q2w3e4r5t")
println(json)
JObject(List((name,JString(luca)), (id,JString(1q2w3e4r5t)), (age,JInt(26)), (url,JString(http://www.nosqlnocry.wordpress.com))))

二、常用操作

2.1 新增一个field

注意,以下两个方法都不会覆盖,若原json中已有height,则新json中会有两个height.

//法1:使用dsl,JObject才有~方法
json = json ~ ("height" -> 175) 
//法2: 使用merge,要求类型和左边一致,所以json为parse出来的JValue时,要用render生成JValue再merge
json = json merge render("height",175)

2.2 更新一个field

使用 transformField

json = json transformField {case JField("name", _) => ("NAME", JString("Luca")) //还可重命名case JField("age", JInt(age)) => ("age", JInt(age+1))//更新值
}json = json merge render("age",26) //若json 中已有"age"

2.3 删除一个field

json = json removeField {case JField("NAME", _) => true //被删除case _ => false
}
// 或等价的
json = json filterField {case JField("NAME", _) => false case _ => true //被保留}

2.4 获取一个field

println(compact(json \\ "age")) // 27 嵌套获取-见下
println(compact(json \ "age"))  // 27
println(compact(json.children(1))) // 27

三、高阶操作

{"name": "luca","id": "1q2w3e4r5t","age": 26,"url": "http://www.nosqlnocry.wordpress.com","url": "https://nosqlnocry.wordpress.com","loginTimeStamps": [1434904257,1400689856,1396629056],"messages": [{"id": 1,"content": "Please like this post!"},{"id": 2,"content": "Forza Roma!"}],"profile": {"id": "my-nickname","score": 123,"avatar": "path.jpg"}
}

3.1 选取field

println(JSON)
//JObject(List((name,JString(luca)), (id,JString(1q2w3e4r5t)), (age,JInt(26)), (url,JString(http://www.nosqlnocry.wordpress.com)), (url,JString(https://nosqlnocry.wordpress.com)), (loginTimeStamps,JArray(List(JInt(1434904257), JInt(1400689856), JInt(1396629056)))), (messages,JArray(List(JObject(List((id,JInt(1)), (content,JString(Please like this post!)))), JObject(List((id,JInt(2)), (content,JString(Forza Roma!))))))), (profile,JObject(List((id,JString(my-nickname)), (score,JInt(123)), (avatar,JString(path.jpg)))))))println(JSON\\"id") //获取所有嵌套的id数据
// prints: JObject(List((id,JString(1q2w3e4r5t)), (id,JInt(1)), (id,JInt(2)), ...println(JSON\"id")//获取第一层的id数据
// prints: JString(1q2w3e4r5t)println(JSON\"url") //如果第一层有多个,则返回JArray
// prints: JArray(List(JString(http://www...), JString(https://nosqlnocry...val messagesIds = (JSON \ "messages") \ "id" //获取JAray中的id数据
println(messagesIds)
// prints: JArray(List(JInt(1), JInt(2)))
println(messagesIds.values)
// prints: List(1,2)
//或用for语句
val messagesIds2=  for {JObject(child) <- JSONJField("id", JInt(id)) <- child} yield idprintln(messagesIds2)// prints: List(1,2)

for语句的<-在JValue中做了特殊处理,会返回所有匹配项。

    for {JObject(child) <- JSON //这回匹配所有JObject,不管是不是嵌套}{println(child)}
//List((name,JString(luca)), (id,JString(1q2w3e4r5t)), (age,JInt(26)), (url,JString(http://www.nosqlnocry.wordpress.com)), (url,JString(https://nosqlnocry.wordpress.com)), (loginTimeStamps,JArray(List(JInt(1434904257), JInt(1400689856), JInt(1396629056)))), (messages,JArray(List(JObject(List((id,JInt(1)), (content,JString(Please like this post!)))), JObject(List((id,JInt(2)), (content,JString(Forza Roma!))))))), (profile,JObject(List((id,JString(my-nickname)), (score,JInt(123)), (avatar,JString(path.jpg))))))
//List((id,JInt(1)), (content,JString(Please like this post!)))
//List((id,JInt(2)), (content,JString(Forza Roma!)))
//List((id,JString(my-nickname)), (score,JInt(123)), (avatar,JString(path.jpg)))

JValue的<-调用的是

    def foreach(f: JValue => Unit): Unit =self.filter(p).foreach(f)

Array的<-调用的是

  def foreach[U](f: A => U): Unit = {var i = 0val len = lengthwhile (i < len) { f(this(i)); i += 1 }}

3.2 取出field

println(compact(render(JSON \ "messages")))
// prints: [{"id":1,"content":"Please like this post!"},{"id":2,"content":"Forza Roma!"}]
println(pretty(render((JSON \ "messages")\"content")))
// prints: [ "Please like this post!", "Forza Roma!" ] // note it is not compacted anymoreprintln(pretty(render(JSON \ "age")))
// prints: 26println(compact(render(JSON \ "name")))
// prints: "luca" // note the apostrophesvar name = for { JString(x) <- (JSON \\ "name") } yield x //或用for表达式去掉双引号
println(name(0))
// prints: lucavar name = (JSON \ "name") //或用values去掉双引号,保留对应基本类型时,推荐这种方法
println(name.values)
// prints: lucaimplicit val formats = DefaultFormats
val name = (JSON \ "name").extract[String]//或直接extract,已知需要的类型时推荐这种方法
println(name)
// prints: luca

name.values 原理:在这里插入图片描述

3.3 查找和过滤filed

//返回第一个遇到的元素
val URL = JSON findField {
case JField("url", _) => true
case _ => false
}
println(URL)
// prints: Some((url,JString(http://www.nosqlnocry.wordpress.com)))// 返回所有符合条件的元素
val URLs = JSON filterField {
case JField("url", _) => true
case _ => false
}
println(URLs)
// prints: List((url,JString(http://www.nosqlnocry...)), (url,JString(https://nosqlnocry...)

3.4 合并与差异另一个Json2:merge和diff

{"messages": [{"id": 3,"content": "how to merge?"}],"url": "anotherURL","loginTimeStamps": 1400689856,"profile": {"avatar": "new.jpg"},"new": "new value"
}

Json1 merge Json2

  1. 如果字段法Json1/f1与Json2/f1结构不同,或者仅具有简单结构,则Json2会替换Json1的f1
  2. 若结构相同且为复杂结构,则会合并
  3. 若Json2/f1在Json1中不存在,则新增
    在这里插入图片描述
    diff 获取两个JSon间的不同(用得少):
val newUserJSON = """{"name":"luca","id": "anotherID","age": 26,"url":"http://www.nosqlnocry.wordpress.com",               "profile":{"id":"another-nickname", "score":99999, "avatar":"path.jpg"}
}
"""    
val Diff(changed, added, deleted) = JSON diff parse(newUserJSON)println(compact(render(changed)))
println(added)
println(pretty(render(deleted)))
/* print:
{"id":"anotherID","profile":{"id":"another-nickname","score":99999}}
JNothing
{"url" : "https://nosqlnocry.wordpress.com","loginTimeStamps" : [ 1434904257, 1400689856, 1396629056 ],"messages" : [ {"id" : 1,"content" : "Please like this post!"}, {"id" : 2,"content" : "Forza Roma!"} ]
}*/

3.5 类和JSon间的转换:decompose, extract, write和read

case class Item(info: String, rank: Int)
case class Item2(info: String, rank: Int, name:String)
implicit val formats: Formats = DefaultFormatsval vMap=Map("info" -> "abcd", "rank" -> 123, "other" -> "dsf")
val jsonStr = write(vMap)
println(jsonStr)
//{"info":"abcd","rank":123,"other":"dsf"}val json = parse(jsonStr)
println(json)val json2 = Extraction.decompose(vMap)//可以理解为等价于parse(write(vMap))
println(json2)val json=parse(jsonStr)
//val json2=
println(json.extract[Map[String,Any]])
//Map(info -> abcd, rank -> 123, other -> dsf)
println(read[Map[String,Any]](jsonStr))//可理解为和json.extract效果一样,但是跳过了将str转为JValue对象的过程
//Map(info -> abcd, rank -> 123, other -> dsf)println(json.extract[Item])//case class 的字段名要和json的field一致,可少不可多与json有的field
//Item(abcd,123)
println(read[Item](jsonStr))
//Item(abcd,123)println(json.extract[Item2])//不可多于json有的field
//报错,org.json4s.MappingException: No usable value for nameprintln(read[Item2](jsonStr))
//报错,org.json4s.MappingException: No usable value for name

不用默认格式:(非scala基类作为父类的话,默认格式解析会出错)

  trait Animalcase class Dog(name: String) extends Animalcase class Fish(weight: Double) extends Animalcase class Animals(animals: List[Animal])implicit val formats1: Formats = DefaultFormatsval formats2: Formats = Serialization.formats(ShortTypeHints(List(classOf[Dog], classOf[Fish])))implicit val mf = manifest[Animals]val ser1 = write(Animals(Dog("pluto") :: Fish(1.2) :: Nil))(formats1)val ser2 = write(Animals(Dog("pluto") :: Fish(1.2) :: Nil))(formats2)println(ser1)//{"animals":[{"name":"pluto"},{"weight":1.2}]}println(ser2)//{"animals":[{"jsonClass":"BasicTest$Dog","name":"pluto"},{"jsonClass":"BasicTest$Fish","weight":1.2}]}println(read[Animals](ser2)(formats2, mf))//Animals(List(Dog(pluto), Fish(1.2)))println(parse(ser2).extract[Animals](formats2,mf))//Animals(List(Dog(pluto), Fish(1.2)))println( read[Animals](ser2)(formats1,mf))// 报错//org.json4s.MappingException: No usable value for animals,No constructor for type Animal, JObject(List((jsonClass,JString(BasicTest$Dog)), (name,JString(pluto))))println( read[Animals](ser1))//等价于println( read[Animals](ser1)(formats1,mf)) ,报错//org.json4s.MappingException: No usable value for animals No constructor for type Animal, JObject(List((name,JString(pluto))))println(parse(ser1).extract[Animals])//报错//org.json4s.MappingException: No usable value for animals No constructor for type Animal, JObject(List((name,JString(pluto))))println(parse(ser2).extract[Animals])//报错//org.json4s.MappingException: No constructor for type Animal, JObject(List((jsonClass,JString(BasicTest$Dog)), (name,JString(pluto))))

参考

官方教程
WORKING WITH JSON IN SCALA USING THE JSON4S LIBRARY (PART ONE)
WORKING WITH JSON IN SCALA USING THE JSON4S LIBRARY (PART TWO)
Purpose of render in json4s

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/101513.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vulnhub系列靶机--- Hackadmeic.RTB1

系列&#xff1a;Hackademic&#xff08;此系列共2台&#xff09; 难度&#xff1a;初级 信息收集 主机发现 netdiscover -r 192.168.80.0/24端口扫描 nmap -A -p- 192.168.80.143访问80端口 使用指纹识别插件查看是WordPress 根据首页显示的内容&#xff0c;点击target 点击…

0822|C++day2 引用+函数重载

一、左值引用(reference) 如果想要实现两个数据的交换&#xff0c;值传递不能交换实参&#xff0c;地址传递可以交换实参&#xff0c;会额外开辟空间 【1】概念 引用其实就是给变量起了一个别名&#xff0c;孙悟空(齐天大圣)C对C的一个最重要的扩充 【2】定义 数据类型 &am…

Leetcode---359周赛

题目列表 2828. 判别首字母缩略词 2829. k-avoiding 数组的最小总和 2830. 销售利润最大化 2831. 找出最长等值子数组 一、判断首字母缩略词 纯模拟&#xff0c;代码如下 class Solution { public:bool isAcronym(vector<string>& words, string s) {string tmp…

Faster RCNN网络数据流总结

前言 在学习Faster RCNN时&#xff0c;看了许多别人写的博客。看了以后&#xff0c;对Faster RCNN整理有了一个大概的了解&#xff0c;但是对训练时网络内部的数据流还不是很清楚&#xff0c;所以在结合这个版本的faster rcnn代码情况下&#xff0c;对网络数据流进行总结。以便…

使用IDEA把Java程序打包成jar

点击左上角File,选择Project Structure 左侧选中Artifacts,点击右侧的号 选择JAR->From modules with dependencies 选择你要运行的main方法所在的类,选好了点击OK Artifacts添加完成后点击右下角OK 在工具栏中找到Build,选择Build Artifacts 刚才创建好的Artifacts,选择Bui…

Python——利用列表推导式实现乘法口诀

直接上代码&#xff1a; print("\n".join([" ".join(["{}*{}{}".format(x, y, x*y) for x in range(1,y1)]) for y in range(1,10)]))结果如下&#xff1a; 1*11 1*22 2*24 1*33 2*36 3*39 1*44 2*48 3*412 4*416 1*55 2*510 3*515 4*520 5*52…

ARM--day7(cortex_M4核LED实验流程、异常源、异常处理模式、异常向量表、异常处理流程、软中断编程、cortex_A7核中断实验)

软中断代码&#xff1a;&#xff08;keil软件&#xff09; .text .global _start _start:1.构建异常向量表b resetb undef_interruptb software_interruptb prefetch_dataabortb data_abortb .b irqb fiq reset:2.系统一上电&#xff0c;程序运行在SVC模式1>>初始化SVC模…

excel中如果A列中某项有多条记录,针对A列中相同的项,将B列值进行相加合并统计

excel中如果A列中某项有多条记录&#xff0c;针对A列中相同的项&#xff0c;将B列值进行相加合并统计。 如&#xff1a; 实现方法&#xff1a; C1、D1中分别输入公式&#xff0c;然后下拉 IF(COUNTIF($A$1:A1,A1)1, A1,"") #A1根据实际情况调整&#xff0c;如果…

从零开始学习YOLOv5 保姆级教程

一、前言 YOLO系列是one-stage且是基于深度学习的回归方法&#xff0c;而R-CNN、Fast-RCNN、Faster-RCNN等是two-stage且是基于深度学习的分类方法。 YOLOv5是一种单阶段目标检测算法&#xff0c;该算法在YOLOv4的基础上添加了一些新的改进思路&#xff0c;使其速度与精度都得…

MPP 还是主流架构吗

MPP 架构&#xff1a; MPP 架构的产品&#xff1a; Impala ClickHouse Druid Doris 很多 OLAP 引擎都采用了 MPP 架构 批处理系统 - 使用场景分钟级、小时级以上的任务&#xff0c;目前很多大型互联网公司都大规模运行这样的系统&#xff0c;稳定可靠&#xff0c;低成本。…

【C++奇遇记】内存模型

&#x1f3ac; 博客主页&#xff1a;博主链接 &#x1f3a5; 本文由 M malloc 原创&#xff0c;首发于 CSDN&#x1f649; &#x1f384; 学习专栏推荐&#xff1a;LeetCode刷题集 数据库专栏 初阶数据结构 &#x1f3c5; 欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如…

2023年03月 C/C++(三级)真题解析#中国电子学会#全国青少年软件编程等级考试

第1题&#xff1a;和数 给定一个正整数序列&#xff0c;判断其中有多少个数&#xff0c;等于数列中其他两个数的和。 比如&#xff0c;对于数列1 2 3 4, 这个问题的答案就是2, 因为3 2 1, 4 1 3。 时间限制&#xff1a;10000 内存限制&#xff1a;65536 输入 共两行&#x…

2023国赛数学建模B题思路模型代码 高教社杯

本次比赛我们将会全程更新思路模型及代码&#xff0c;大家查看文末名片获取 之前国赛相关的资料和助攻可以查看 2022数学建模国赛C题思路分析_2022国赛c题matlab_UST数模社_的博客-CSDN博客 2022国赛数学建模A题B题C题D题资料思路汇总 高教社杯_2022国赛c题matlab_UST数模社…

svg mask和stroke冲突问题

目录 先说结论各种样例首先是水平、垂直的线然后是斜线如果是图形加stroke呢用《g》标签包起来呢 总结 先说结论 实际上svg里&#xff0c;mask对svg内元素起作用的并非元素本身&#xff0c;而是元素几何形状的外包矩形&#xff0c;特别是和stroke有冲突&#xff0c;会产生奇怪…

STM32 CubeMX (第二步Freertos任务通信:队列、信号量、互斥量,事件组,任务通知)

STM32 CubeMX STM32 CubeMX ____Freertos任务通信&#xff1a;队列、信号量、互斥量&#xff0c;事件组&#xff0c;任务通知 STM32 CubeMX一、STM32 CubeMX设置时钟配置HAL时基选择TIM1&#xff08;不要选择滴答定时器&#xff1b;滴答定时器留给OS系统做时基&#xff09;使用…

苍穹外卖 day3 实现登录过程中MD5加密

一 原来是明文存的 密码可见度太高&#xff0c;MD5加密为密文图像 效果 二 密文实现步骤 修改明文密码&#xff0c;改成密文 123456 密文值&#xff1a;e10adc3949ba59abbe56e057f20f883e代码如下所示 在这里插入代码片 package com.sky.service.impl;import com.sky.con…

Vue使用Animate.css

说一下Animate.css这个动画库&#xff0c;很多的动画在这个库里面都定义好了&#xff0c;我们用的时候可以直接使用里面的类名就可以了&#xff0c;就是直接目标元素绑定对应的类名就可以实现动画效果&#xff0c;非常方便&#xff0c;库其实也相对简单&#xff0c;使用起来也简…

数据结构(3)

线性表是多个具有相同特征的数据的有限序列。 前驱元素&#xff1a;A在B前面&#xff0c;称A为B的前驱元素。 后继元素&#xff1a;B在A后面&#xff0c;称B为A的后继元素。 线性表特征&#xff1a; 1.一个元素没有前驱元素&#xff0c;就是头结点&#xff1b; 2.最后一个…

法线矩阵推导

法线矩阵推导 https://zhuanlan.zhihu.com/p/72734738 https://juejin.cn/post/7113952418613690382 https://blog.csdn.net/wangjianxin97?typeblog 1、为什么需要法线矩阵 vec3 normalEyeSpace modelViewMatrix * normal;如果模型矩阵执行了非等比缩放, 顶点的改变会导致法…

PSP - 蛋白质结构预测 AlphaFold2 的结构模版 (Template) 搜索与特征逻辑

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/132427617 结构模版 (Template) 是一种已知的蛋白质结构&#xff0c;可以作为 AlphaFold2 蛋白质结构预测的参考&#xff0c;AlphaFold2 可以从多…