一 快速安装
GJSON路径是一种文本字符串语法,它描述了从JSON有效载荷中快速检索值的搜索模式。
GJSON路径易于表示为一系列由字符分隔的组件。
除了字符之外,还有一些字符具有特殊含义: ,
、 .
、 |
、 #
、 @
、 \
、 *
、 !
、 ?
当json的key里包含特殊字符且需要根据key进行提取时,需要进行转义操作
安装命令如下
1 | go get -u github.com/tidwall/gjson |
github的地址为 https://github.com/tidwall/gjson
语法介绍可见 https://github.com/tidwall/gjson/blob/master/SYNTAX.md
该语法可以在 GJSON Playground https://gjson.dev/ 上在线运行查看结果
使用的json示例如下:
1 | { |
二 基本使用
2.1 快速启动
1 | package main |
输出结果为
1 | Prichard |
在许多情况下,您只需要按对象名称或数组索引检索值。
对于实例json,以下语法对应的结果如下:
1 | name.last "Anderson" |
2.2 结果类型
GJSON支持json类型string
、number
、bool
和null
。数组和对象作为其原始json类型返回。
Result
类型包含以下内容之一:
1 | bool, for JSON booleans |
要直接访问值:
1 | result.Type // can be String, Number, True, False, Null, or JSON |
有多种方便的函数可以处理结果:
1 | result.Exists() bool |
result.Value()
函数返回的类型是interface{}
,它是以下Go类型之一:
1 | boolean >> bool |
result.Array()
函数返回一个值数组。如果结果表示一个不存在的值,那么将返回一个空数组。如果结果不是JSON数组,则返回值将是包含一个结果的数组。
2.3 64位整数
result.Int()
和result.Uint()
调用能够读取所有64位,允许使用大型JSON整数。
1 | result.Int() int64 // -9223372036854775808 to 9223372036854775807 |
2.4 Simple Parse and Get
可以用Parse(json)
函数执行简单的解析,result.Get(path)
函数搜索结果。
例如,所有这些都将返回相同的结果:
1 | gjson.Parse(json).Get("name").Get("last") |
2.5 检查值是否存在
有时你只想知道一个值是否存在。
1 | value := gjson.Get(json, "name.last") |
2.6 json验证
Get*
和Parse*
函数的使用前提是一个正常的json,异常的json数据不会引起panic
,但是会返回一个意想不到的结果。
如果您使用的是来自不可预测的源的JSON,那么您可能需要在使用GJSON之前进行验证。
1 | if !gjson.Valid(json) { |
2.7 转换为map
将json转换为map[string]interface{}
的结构
1 | m, ok := gjson.Parse(json).Value().(map[string]interface{}) |
2.8 使用字节
如果JSON包含在[]byte
切片中,则有GetBytes
函数。这优于Get(string(data), path)
1 | var json []byte = ... |
如果您正在使用gjson.GetBytes(json,path)
函数,并且希望避免将result.Raw
转换为[]byte
,则可以使用以下模式:
1 | var json []byte = ... |
这是原始json的无分配子片。此方法使用result.Index
字段,该字段是原始json中原始数据的位置。result.Index
的值可能等于零,在这种情况下result.Raw
被转换为[]byte
。
2.9 同时获取多个值
GetMany
函数可用于同时获取多个值。
1 | results := gjson.GetMany(json, "name.first", "name.last", "age") |
返回值是一个[]Result
,它将始终包含与输入路径完全相同数量的项。
三通配符
key可以包含特殊通配符和.
、*
和?
1 | child*.2 "Jack" |
三 转义
特殊字符需要转义才能使用
1 | fav\.movie "Deer Hunter" |
在源代码中硬编码路径时,还需要确保字符正确转义
1 | // Go |
1 | // Rust |
四 数组
4.1 基本使用
#
字符允许深入JSON数组,也可以使用#
获取数组的长度
1 | friends.# 3 |
对于以下json
1 | { |
可以使用programmers.#.lastName
查询
1 | result := gjson.Get(json, "programmers.#.lastName") |
还可以查询数组中的对象:
1 | name := gjson.Get(json, `programmers.#(lastName="Hunter").firstName`) |
4.2 遍历对象或数组
ForEach
函数允许快速遍历对象或数组。键和值被传递给对象的迭代器函数。仅为数组传递值。从迭代器返回false
将停止迭代。
1 | result := gjson.Get(json, "programmers") |
五 查询
5.1 基本查询
可以使用 #(...)
查询数组的第一个符合条件的结果或者使用#(...)#
查询全部符合条件的结果。查询语法支持 ==
, !=
, <
, <=
, >
, >=
比较运算符,简单的模式匹配支持%
(like)和!%
(not like)
1 | friends.#(last=="Murphy").first "Dale" |
要查询数组中的非对象值,可以放弃运算符右侧的字符串。
1 | children.#(!%"*a*") "Alex" |
5.2 嵌套查询
1 | friends.#(nets.#(=="fb"))#.first >> ["Dale","Roger"] |
请注意,在v1.3.0之前,查询使用#[…]
括号。为了避免与新的多路径语法混淆,v1.3.0中对此进行了更改。为了向后兼容,#[…]
将继续工作直到下一个主要版本。
~
(波浪号)运算符将在比较之前将值转换为布尔值。
l例如对下面的json
1 | { |
可以查询所有true(ish)或false(ish)值:
1 | vals.#(b==~true)#.a >> [1,2,6,7,8] |
最后一个不存在的值被视为false
5.3 构造新json
使用选择器语法将多个路径连接到新的JSON文档中。
1 | {name.first,age,"murphys":friends.#(last="Murphy")#.first} |
六 点 和 管道符
.
是标准分隔符,但也可以使用|
,在大多数情况下,它们都会返回相同的结果.
主要注意的是,在使用#
查询数组时,|
与.
的用法是不同的
1 | friends.0.first "Dale" |
分析如下如下:
friends.#(last="Murphy")#
获取到的结果为
1 | [{"first": "Dale", "last": "Murphy", "age": 44},{"first": "Jane", "last": "Murphy", "age": 47}] |
.first
后缀会在每个数组元素返回之前处理它的first
路径,所以最终结果为
1 | ["Dale","Jane"] |
但|first
后缀实际上处理前一个结果之后的第一个路径。由于前面的结果是一个数组,而不是一个对象,因此无法处理,因为first不存在。
然而,|0后缀返回
1 | {"first": "Dale", "last": "Murphy", "age": 44} |
因为0是上一个结果的第一个索引。
七 修饰符
7.1 内置修饰符
修饰符是对JSON执行自定义处理的路径组件。
例如,在上面的JSON负载上使用内置的@reverse
修饰符将反转子数组:
1 | children.@reverse ["Jack","Alex","Sara"] |
内置修饰符的含义如下:
@reverse
:反转数组或对象的成员。@ugly
:从 JSON 中删除所有空格。@pretty
:使 JSON 更具人类可读性。@this
:返回当前元素。它可用于检索根元素。@valid
:确保 JSON 文档有效。@flatten
:展平数组。@join
:将多个对象合并为一个对象。@keys
:返回对象的键数组。@values
:返回对象的值数组。@tostr
:将 json 转换为字符串。包装 json 字符串。@fromstr
:从 json 转换字符串。解包 json 字符串。@group
:对对象数组进行分组。请参阅 e4fc67c。
7.2 修饰符参数
修饰符可以接受可选参数。参数可以是有效的JSON负载,也可以是字符。
例如,修饰符将json对象作为@pretty
的参数
1 | @pretty:{"sortKeys":true} |
这使得json很漂亮,并对其所有键进行排序。
1 | { |
使用实例
1 | children.@reverse >> ["Jack","Alex","Sara"] |
7.3 自定义修饰符
可以添加自定义修改器。
例如这里我们创建了一个修饰符,它使整个json文档变为大写或小写。
1 | gjson.AddModifier("case", func(json, arg string) string { |
自定义修改器在Rust版本中尚不可用
八 多路径
从v1.3.0开始,GJSON增加了将多个路径连接在一起以形成新文档的功能。在或之间包装逗号分隔的路径将分别产生一个新的数组或对象
例如
1 | {name.first,age,"the_murphys":friends.#(last="Murphy")#.first} |
在这里,我们为姓为“Murphy”的朋友选择了名字、年龄和名字。
您将注意到,可以提供一个可选的键,在本例中为“themurphys”,以强制将键分配给一个值。否则,将使用实际字段的名称,在本例中为“first”。如果无法确定名称,则使用“”。
运行结果如下:
1 | {"first":"Tom","age":37,"the_murphys":["Dale","Jane"]} |
九 常量
从v1.12.0开始,GJSON增加了对json文本的支持,这提供了一种构造json静态块的方法。这在使用多路径构建新的json文档时尤其有用。
json文本以“!”开头声明字符。
例如,使用给定的多路径:
1 | {name.first,age,"company":!"Happysoft","employed":!true} |
这里我们选择了名字和年龄。然后添加两个新字段,“company”和“employed”。
运行结果为
1 | {"first":"Tom","age":37,"company":"Happysoft","employed":true} |
十 JSON行
支持使用..
前缀,将多行文档视为数组。
对于以下文本
1 | {"name": "Gilbert", "age": 61} |
对应的结果为
1 | ..# >> 4 |
ForEachLines
函数将遍历JSON行。
1 | gjson.ForEachLine(json, func(line gjson.Result) bool{ |