Go--gjson
GJSON 是一个用于处理 JSON 数据的 Go 语言库。它提供了一些方便的功能,例如解析 JSON 字符串、查询 JSON 对象、生成 JSON 对象等
下载gjson: go get -u github.com/tidwall/gjson
1、使用
传入 JSON 串和要读取的键路径,路径使用点号语法,如 "name.last "或 "age"。一旦找到值,就会立即返回。
路径是一系列用点分隔的键。键可以包含特殊的通配符 "*"和"? 要访问数组值,使用索引作为键。要获取数组中的元素个数或访问子路径,请使用 "#"字符。点和通配符可以用'\'转义。
例:
package main import (
"fmt"
"github.com/tidwall/gjson"
) func main() {
//{
// "name": {"first": "Tom", "last": "Anderson"},
// "age":37,
// "children": ["Sara","Alex","Jack"],
// "friends": [
// {"first": "James", "last": "Murphy"},
// {"first": "Roger", "last": "Craig"}
// ]
// }
//设置json字符串
jsonStr := `{"name": {"first": "Tom", "last": "Anderson"}, "age": 37, "children": ["Sara", "Alex", "Jack"], "friends": [{"first": "James", "last": "Murphy"}, {"first": "Roger", "last": "Craig"}]}` //获取数据
name1 := gjson.Get(jsonStr, "name") //默认返回的是gjson.Result类型,如果是直接打印,可直接使用,若是需进一步操作,建立转换成对应类型
name2 := gjson.Get(jsonStr, "name").String() //从 jsonStr 中获取 "name" 字段的值,然后通过调用 .String() 方法,将获取到的值转换为字符串类型,如果 "name" 字段的值不是字符串类型,它会被转换为字符串
name3 := gjson.Get(jsonStr, "name").Str //也是从 jsonStr 中获取 "name" 字段的值,但是是直接获取该字段的值,没有进行类型转换,如果"name"字段的值不是字符串类型,则将保持原来的类型
//如果确定 "name" 字段的值一定是字符串类型,那么使用 .Str 是更简洁的方式。如果不确定 "name" 字段的值是什么类型,或者想要确保它是一个字符串类型,那么使用 .String() 进行显式转换是更安全的选择。 fmt.Printf("值类型:%T,值:%v\n", name1, name1)
fmt.Printf("值类型:%T,值:%v\n", name2, name2)
fmt.Printf("值类型:%T,值:%v\n", name3, name3) //无法输出值是因为name" 是一个嵌套的 JSON 对象,而不是一个字符串
first := gjson.Get(jsonStr, "name.first").Str //需要进一步获取值
fmt.Printf("值类型:%T,值:%v\n", first, first)
}
输出结果:
值类型:gjson.Result,值:{"first": "Tom", "last": "Anderson"}
值类型:string,值:{"first": "Tom", "last": "Anderson"}
值类型:string,值:
值类型:string,值:Tom
2、类型转换
方法 | 描述 |
String() | 尝试将此值转换为string |
Int() | 尝试将此值转换为int64 |
Uint64() | 尝试将此值转换为uint64 |
Float64() | 尝试将此值转换为float64 |
Bool() | 尝试将此值转换为布尔型 |
3、键路径
键路径实际上是以.
分隔的一系列键。gjson
支持在键中包含通配符*
和?
,*
匹配任意多个字符,?
匹配单个字符,例如ca*
可以匹配cat/cate/cake
等以ca
开头的键,ca?
只能匹配cat/cap
等以ca
开头且后面只有一个字符的键。
数组使用键名 + .
+ 索引(索引从 0 开始)的方式读取元素,如果键pets
对应的值是一个数组,那么pets.0
读取数组的第一个元素,pets.1
读取第二个元素。
数组长度使用**键名 + .
+ #
**获取,例如pets.#
返回数组pets
的长度。
如果键名中出现.
,那么需要使用\
进行转义
例(使用上面的json字符串):
//设置json字符串
jsonStr := `{"name": {"first": "Tom", "last": "Anderson"}, "age": 37, "children": ["Sara", "Alex", "Jack"], "friends": [{"first": "James", "last": "Murphy"}, {"first": "Roger", "last": "Craig"}]}` //获取数据
fmt.Println("name.last:", gjson.Get(jsonStr, "name.last"))
fmt.Println("age:", gjson.Get(jsonStr, "age"))
fmt.Println("children:", gjson.Get(jsonStr, "children"))
fmt.Println("children.#:", gjson.Get(jsonStr, "children.#")) //返回数组的长度
fmt.Println("children.1:", gjson.Get(jsonStr, "children.1")) //读取数组下标为1的元素值(注意下标从0开始)
fmt.Println("child*.2:", gjson.Get(jsonStr, "child*.2")) //*匹配,再读取下标为2的元素值
fmt.Println("c?ildren.0:", gjson.Get(jsonStr, "c?ildren.0")) //也是匹配,不过只匹配一个字符,再读取下标为0的元素值
fmt.Println("friends.#.first:", gjson.Get(jsonStr, "friends.#.first")) //如果数组#后还有内容,则以后面的路径读取数组中的每个元素,返回一个新的数组。所以该查询返回的数组所有friends的first字段组成
fmt.Println("friends.1.first:", gjson.Get(jsonStr, "friends.1.first")) //读取friends第 2 个元素的last字段
输出结果:
name.last: Anderson
age: 37
children: ["Sara", "Alex", "Jack"]
children.#: 3
children.1: Alex
child*.2: Jack
c?ildren.0: Sara
friends.#.first: ["James","Roger"]
friends.1.first: Roger
3.1 数组
对于数组,gjson
还支持按条件查询元素,#(条件)
返回第一个满足条件的元素,#(条件)#
返回所有满足条件的元素。括号内的条件可以有==
、!=
、<
、<=
、>
、>=
,还有简单的模式匹配%
(符合某个模式),!%
(不符合某个模式):
package main import (
"fmt"
"github.com/tidwall/gjson"
) func main() {
//设置json字符串
var jsonStr = `{"name": {"first": "Tom", "last": "Anderson"}, "age": 37, "children": ["Sara", "Alex", "Jack"], "fav.movie": "Dear Hunter", "friends": [{"first": "Dale", "last": "Murphy", "age": 44, "nets": ["ig", "fb", "tw"]}, {"first": "Roger", "last": "Craig", "age": 68, "nets": ["fb", "tw"]}, {"first": "Jane", "last": "Murphy", "age": 47, "nets": ["ig", "tw"]}]}`
//{
// "name":{"first":"Tom", "last": "Anderson"},
// "age": 37,
// "children": ["Sara", "Alex", "Jack"],
//"fav.movie": "Dear Hunter",
//"friends": [
// {"first": "Dale", "last":"Murphy", "age": 44, "nets": ["ig", "fb", "tw"]},
// {"first": "Roger", "last": "Craig", "age": 68, "nets": ["fb", "tw"]},
// {"first": "Jane", "last": "Murphy", "age": 47, "nets": ["ig", "tw"]}
// ]
//} //输出数据
fmt.Println(gjson.Get(jsonStr, `friends.#(last="Murphy").first`)) //返回数组friends中第一个last为Murphy的元素;.first表示取出该元素的first字段返回
fmt.Println(gjson.Get(jsonStr, `friends.#(last="Murphy")#.first`)) //返回数组friends中所有的last为Murphy的元素,然后读取它们的first字段放在一个数组中返回
fmt.Println(gjson.Get(jsonStr, "friends.#(age>37)#.last")) //返回数组friends中所有年龄大于 45 的元素,然后读取它们的last字段返回
fmt.Println(gjson.Get(jsonStr, `friends.#(first%"D*").last`)) //返回数组friends中第一个first字段满足模式D*的元素,取出其last字段返回
fmt.Println(gjson.Get(jsonStr, `friends.#(first!%"D*").last`)) //返回数组friends中第一个first字段**不**满足模式D*的元素,读取其last`字段返回
fmt.Println(gjson.Get(jsonStr, `friends.#(nets.#(=="fb"))#.first`)) //这是个嵌套条件,friends.#(nets.#(=="fb"))#返回数组friends的元素的nets字段中有fb的所有元素,然后取出first字段返回
}
输出结果:
Dale
["Dale","Jane"]
["Murphy","Craig","Murphy"]
Murphy
Craig
["Dale","Roger"]
4、 一次获取多个值
调用gjson.Get()
一次只能读取一个值,多次调用又比较麻烦,gjson
提供了GetMany()
可以一次读取多个值,返回一个数组[]gjson.Result
。
//获取数据,使用3里面的字符串
results := gjson.GetMany(jsonStr, "name", "age", "children.#", "friends.#.first")
for _, result := range results {
fmt.Println(result)
}
//输出结果
// {"first": "Tom", "last": "Anderson"}
// 37
// 3
// ["Dale","Roger","Jane"]
5、校验json
调用gjson.Get()
时,gjson
假设我们传入的 JSON 串是合法的。如果 JSON 非法也不会panic
,这时会返回不确定的结果
gjson.Valid()
检测 JSON 串是否合法:
if !gjson.Valid(json) {
fmt.Println("error")
} else {
fmt.Println("ok")
}
6、遍历
gjson.Get()
方法返回一个gjson.Result
类型的对象,json.Result
提供了ForEach()
方法用于遍历。该方法接受一个类型为func (key, value gjson.Result) bool
的回调函数。遍历对象时key
和value
分别为对象的键和值;遍历数组时,value
为数组元素,key
为空(不是索引)。回调返回false
时,遍历停止。
results := gjson.Get(jsonStr, "friends") //获取初始数据,3里面的字符串
results.ForEach(func(k, result gjson.Result) bool { //遍历,一般不需要k,可用_忽略
first := gjson.Get(result.Raw, "first") //可以再次根据键路径获取更为详细的数据
fmt.Printf("k:%v,v:%v\n", k, results) //输出键值
fmt.Println(first) //输出friends数组里的first元素值
return true
})
输出结果:
k:0,v:[{"first": "Dale", "last": "Murphy", "age": 44, "nets": ["ig", "fb", "tw"]}, {"first": "Roger", "last": "Craig", "age": 68, "nets": ["fb", "tw"]}, {"first": "Jane", "last": "Murphy", "age": 47, "nets": ["ig", "tw"]}]
Dale
k:1,v:[{"first": "Dale", "last": "Murphy", "age": 44, "nets": ["ig", "fb", "tw"]}, {"first": "Roger", "last": "Craig", "age": 68, "nets": ["fb", "tw"]}, {"first": "Jane", "last": "Murphy", "age": 47, "nets": ["ig", "tw"]}]
Roger
k:2,v:[{"first": "Dale", "last": "Murphy", "age": 44, "nets": ["ig", "fb", "tw"]}, {"first": "Roger", "last": "Craig", "age": 68, "nets": ["fb", "tw"]}, {"first": "Jane", "last": "Murphy", "age": 47, "nets": ["ig", "tw"]}]
Jane
PS D:\Users\W9010315\GolandProjects\test> go run .\gjson.go
k:0,v:[{"first": "Dale", "last": "Murphy", "age": 44, "nets": ["ig", "fb", "tw"]}, {"first": "Roger", "last": "Craig", "age": 68, "nets": ["fb", "tw"]}, {"first": "Jane", "last": "Murphy", "age": 47, "nets": ["ig", "tw"]}]
Dale
k:1,v:[{"first": "Dale", "last": "Murphy", "age": 44, "nets": ["ig", "fb", "tw"]}, {"first": "Roger", "last": "Craig", "age": 68, "nets": ["fb", "tw"]}, {"first": "Jane", "last": "Murphy", "age": 47, "nets": ["ig", "tw"]}]
Roger
k:2,v:[{"first": "Dale", "last": "Murphy", "age": 44, "nets": ["ig", "fb", "tw"]}, {"first": "Roger", "last": "Craig", "age": 68, "nets": ["fb", "tw"]}, {"first": "Jane", "last": "Murphy", "age": 47, "nets": ["ig", "tw"]}]
Jane
本文参考:https://darjun.github.io/2020/03/22/godailylib/gjson/
7、补充
7.1 Exists()
该函数用于检查指定的键是否存在于json对象中,存在则返回true,否则返回false。可用来检测填写的键路径是否正确
// 解析 JSON 数据
if gjson.Get(jsonStr, "name").Exists() {
fmt.Println("name 键存在")
} else {
fmt.Println("name 键不存在")
}
Go--gjson的更多相关文章
- 解决GJson 获取web api数据出现Not a JsonObject问题
服务器端web api服务采用asp.net web api编写,对请求的数据序列化成Json格式的字符串进行传递. 客户端采用Java进行接收处理,处理采用GJson进行解析,出现Not a Jso ...
- Tomjson - 一个"短小精悍"的 json 解析库
Tomjson,一个"短小精悍"的 json 解析库,tomjson使用Java语言编写,主要作用是把Java对象(JavaBean)序列化为json格式字符串,将json格式字符 ...
- JavaSE18章_JSON解析详解
一.JSON简介 JSON(JavaScript Object Notation),是一种轻量级的数据交换格式.JSON是存储和交换文本信息的,语法类似 XML.易于人阅读和编写,同时也易于机器解析和 ...
- android中Json的一些应用
JSON(JavaScript Object Notation) :一种轻量级的数据交换格式,基于JavaScript的一个子集. JSON采用完全独立于语言的文本格式,使JSON成为理想的数据交换语 ...
- android json解析详细介绍之gson
废话不多说,什么json是轻量级数据交换标准:自己百度去深入了解:这里有三种json解析工具.本人只用过其中两种: 1.Google Json利器之Gson 评价:简单,方便. 2.阿里巴巴 ...
- js,jquery转json的几种方法
一.原生js转json, eval()方法,不需要引入外部插件; //由JSON字符串转换为JSON对象 var obj = eval('(' + jsonStr + ')'); 或者 var obj ...
- 第一次使用Android Studio时你应该知道的一切配置(三):gradle项目构建
[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/ ...
- 第一次使用Android Studio时你应该知道的一切配置(二):新建一个属于自己的工程并安装Genymotion模拟器
[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4 ...
- 【转】第一次使用Android Studio时你应该知道的一切配置(三):gradle项目构建
原文网址:http://www.cnblogs.com/smyhvae/p/4456420.html [声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.c ...
- Tomjson - json 解析库
Tomjson - 一个"短小精悍"的 json 解析库 Tomjson,一个"短小精悍"的 json 解析库,tomjson使用Java语言编写,主要作用是把 ...
随机推荐
- .NET开源全面方便的第三方登录组件集合 - MrHuo.OAuth
前言 我相信做开发的同学应该都对接过各种各样的第三方平台的登录授权,来获取用户信息(如:微信登录.支付宝登录.QQ登录.GitHub登录等等).今天给大家推荐一个.NET开源好用的.全面的.方便第三方 ...
- 在路上---学习篇(一)Python 数据结构和算法 (6)基于GA(遗传)算法的小案例
独白 最近了解到一种算法叫遗传算法,对其比较感兴趣,研究了一下,是模拟达尔文生物进化论的自然选择和遗传学机理的生物进化过程的计算模型,是一种通过模拟自然进化过程搜索最优解的方法.遗传算法是从代表问题可 ...
- Hive的使用以及如何利用echarts实现可视化在前端页面展示(四)---连接idea使用echarts可视化界面
说来惭愧,我的javaweb烂得一批,其他步骤我还是很顺利地,这个最简单的,我遇到了一系列问题.只能说,有时候失败也是一种成功吧 这一步其实就是正常的jdbc,没什么可说明的,但是关于使用echart ...
- ERP到底是什么?
ERP,全称企业资源计划,ERP系统主要是优化企业内部的业务流程,用信息化管控的方式进行一系列板块的管理,它可以看作是进销存系统的进阶版,主要针对供应链中下游. ERP的业务覆盖范围广,实际上它更加侧 ...
- Codeforces Round #691 (Div. 2) D - Glass Half Spilled(DP)
题目 补下因实验漏掉的CF(还以为是晚上,没想到是下午开始).前三题过的很顺利,到D题时想了会发现数据很小爆搜貌似能过,就以为是道水题,交了一发T了,胡乱加了点剪枝还是T.逐渐意识到事情的严重性.考虑 ...
- Hdu4742 (CDQ分治)
题意:给出n个三维点对(x,y,z),可随意排列,求三维非严格最长上升子序列长度和最长上升子序列数量. 输入格式:第一行为一整数T表示用例组数,每组用例第一行为一整数n表示点数,之后n行每行三个整数x ...
- wps表格求标准差怎么算?
在WPS表格中,要计算标准差,可以使用STDEV函数.标准差是一种衡量数据集合离散程度的统计指标.下面我将详细介绍如何使用STDEV函数来计算标准差. STDEV函数的语法为:STDEV(range) ...
- Go笔记(1)-变量的详细用法
变量 (1)变量的定义 Go语言是静态类型的语言,所有类型都需要明确的定义. var是声明变量的关键字 使用格式:var 变量名 变量类型 变量命名规范:遵循驼峰格式,首个单词小写,每个新单词的首字母 ...
- Spring中Bean的加载方式~
1.方式一:基于spring.xml方式配置Bean user import lombok.Data; /** * @author : ly */ @Data public class User { ...
- 华企盾DSC导致金蝶导入Excel导入不了的问题
需要把Excel的OLE控制关掉,并且金蝶的进程和Excel的进程高级设置要么都启用重定向,要么都不启用重定向