简介
JSON 是一种非常流行的数据交换格式。每种编程语言都有很多操作 JSON 的库,标准库、第三方库都有。Go 语言中标准库内置了 JSON 操作库encoding/json
。我们之前也介绍过专门用于查询 JSON 串的库gjson和专门用于修改 JSON 串的库sjson,还有一个非常方便的操作 JSON 数据的命令行工具jj。今天我们再介绍一个 JSON 工具库——gabs
。gabs
是一个用来查询和修改 JSON 串的库。它使用encoding/json
将一般的 JSON 串转为map[string]interface{}
,并提供便利的方法操作map[string]struct{}
。
快速使用
本文代码使用 Go Modules。
创建目录并初始化:
$ mkdir gabs && cd gabs
$ go mod init github.com/darjun/go-daily-lib/gabs
安装gabs
,目前最新版本为v2
,推荐使用v2
:
$ go get -u github.com/Jeffail/gabs/v2
使用:
package main
import (
"github.com/Jeffail/gabs/v2"
"fmt"
)
func main() {
jObj, _ := gabs.ParseJSON([]byte(`{
"info": {
"name": {
"first": "lee",
"last": "darjun"
},
"age": 18,
"hobbies": [
"game",
"programming"
]
}
}`))
fmt.Println("first name: ", jObj.Search("info", "name", "first").Data().(string))
fmt.Println("second name: ", jObj.Path("info.name.last").Data().(string))
gObj, _ := jObj.JSONPointer("/info/age")
fmt.Println("age: ", gObj.Data().(float64))
fmt.Println("one hobby: ", jObj.Path("info.hobbies.1").Data().(string))
}
首先,我们调用gabs.ParseJSON()
方法解析传入的 JSON 串,得到一个gabs.Container
对象。后续通过该gabs.Container
对象来查询和修改解析出来的数据。
gabs
提供 3 种查询方式:
以
.
分隔的路径调用Path()
方法;将路径各个部分作为可变参数传入
Search()
方法;使用
/
分隔的路径调用JSONPointer()
方法。
上述方法内部实现最终都是调用相同的方法,只是使用上稍微有些区别。注意:
3 个方法最终都返回一个
gabs.Container
对象,我们需要调用其Data()
获取内部的数据,然后做一次类型转换得到实际的数据;如果传入的路径有误或路径下无数据,则
Search/Path
方法返回的gabs.Container
对象内部数据为nil
,即Data()
方法返回nil
,而JSONPointer
方法返回err
。实际使用时注意进行空指针和错误判断;如果路径某个部分对应的数据类型为数组,则可以在后面追加索引,读取对应索引下的数据,如
info.hobbies.1
;JSONPointer()
参数必须以/
开头。
运行结果:
$ go run main.go
first name: lee
second name: darjun
age: 18
one hobby: programming
查询 JSON 串
上一节中我们介绍过,在gabs
中,路径有 3 种表示方式。这 3 种方式对应 3 个基础的查询方法:
Search(hierarchy ...string)
:也有一个简写形式S
;Path(path string)
:path
以.
分隔;JSONPointer(path string)
:path
以/
分隔。
它们的基本用法上面已经介绍过了,对于数组我们还能对每个数组元素做递归查询。在下面例子中,我们依次返回数组members
中每个元素的name
、age
和relation
字段:
func main() {
jObj, _ := gabs.ParseJSON([]byte(`{
"user": {
"name": "dj",
"age": 18,
"members": [
{
"name": "hjw",
"age": 20,
"relation": "spouse"
},
{
"name": "lizi",
"age": 3,
"relation": "son"
}
]
}
}`))
fmt.Println("member names: ", jObj.S("user", "members", "*", "name").Data())
fmt.Println("member ages: ", jObj.S("user", "members", "*", "age").Data())
fmt.Println("member relations: ", jObj.S("user",