分享
  1. 首页
  2. 文章

json 二 开源库gjson的用法

xiaojun1195 · · 3242 次点击 · · 开始浏览
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

二 开源库gjson

用过Go语言的都知道,在项目中Go语言json包肯定是不足以满足千变万化的需求的。Go语言中Unmarshal函数会把整个JSON字符串解析成Go语言结构体实例,如果这个实例很大,JSON很长,我们只需要用到这个实例中的一个属性,那么这个转换就浪费了很多性能。所以,在项目中大家一般会使用第三方JSON包。
2.1 gjson

gjson是Github上很受欢迎的Go语言JSON开源库,可以通过级联方式直接获取下级某个属性,可以获取某个JSON数组的第一个元素,最后一个元素,元素个数等等。gjson到现在已经有6000多star。


2.2 性能对比

gjson与内置JSON库、其他开源JSON库的性能对比结果,可以看到gjson性能远远优于内置json库和其他开源库:



2.3 级联获取下级属性

gjson可以通过xx.xx直接获取某个下级属性,不需要把整个JSON解析成Go结构体实例后再获取:
import (
"fmt"
"github.com/tidwall/gjson"
)
const json = `{"name":{"first":"Janet","last":"Prichard"},"age":47}`

func main() {
value := gjson.Get(json, "name.last") // 直接获取name中的last属性值
fmt.Println(value.String()) // 输出:Prichard
}
2.4 获取JSON数组元素、元素个数、第一个元素:

gjson可以通过.#获取JSON数组元素个数,.1获取JSON数组的第一个元素,可以通过*来匹配JSON字段名:
const json = `{
"name": {"first": "Tom", "last": "Anderson"},
"age":37,
"children": ["Sara","Alex","Jack"]
}`

func main() {
value := gjson.Get(json, "children") // 获取children数组
fmt.Println(value.String()) // 输出:["Sara","Alex","Jack"]

value = gjson.Get(json, "children.#") // 获取children数组元素个数
fmt.Println(value.String()) // 输出:3

value = gjson.Get(json, "children.1") // 获取children数组的第二个元素(index为1)
fmt.Println(value.String()) // 输出:Alex

value = gjson.Get(json, "child*.2") // 获取child*数组的第三个元素(index为2),*可以匹配任意多个字符,此处能匹配到children数组
fmt.Println(value.String()) // 输出:Jack
}
2.5 获取JSON数组下所有元素的某个属性值,获取JSON数组下符合匹配条件的所有元素的某个属性值

可以使用#(...)来寻找数组中第一个匹配的元素,使用#(...)#寻找数组中所有匹配的元素:
const json = `{
"name": {"first": "Tom", "last": "Anderson"},
"friends": [
{"first_name": "Dale", "last_name": "Murphy", "age": 44, "nets": ["ig", "fb", "tw"]},
{"first_name": "Roger", "last_name": "Craig", "age": 68, "nets": ["fb", "tw"]},
{"first_name": "Jane", "last_name": "Murphy", "age": 47, "nets": ["ig", "tw"]}
]
}`

func main() {
// friends数组中每个元素都是一个JSON对象
value := gjson.Get(json, "friends.#.first_name") // #没有带表达式,用于获取数组的所有元素。此句匹配friends数组中所有元素对象的first_name属性。
fmt.Println(value.String()) // 输出:["Dale","Roger","Jane"]

value = gjson.Get(json, "friends.1.first_name") // 匹配friends数组中第二个元素对象(index为1)的first_name属性。
fmt.Println(value.String()) // 输出:Roger

value = gjson.Get(json, `friends.#(last_name=="Murphy").first_name`) // #带表达式,用于获取符合匹配条件的第一个数组元素。此句匹配friends数组中last_name属性为Murphy的第一个数组元素的first_name属性。
fmt.Println(value.String()) // 输出:Dale

value = gjson.Get(json, `friends.#(age>45)#.last_name`) // #带表达式,后面来跟了一个#,用于获取符合匹配条件的所有数组元素。此句匹配friends数组中age属性大于45的所有数组元素的last_name属性。
fmt.Println(value.String()) // 输出:["Craig","Murphy"]
}
2.6 判断JSON属性是否存在

value := gjson.Get(json, "name.last")
if !value.Exists() {
println("no last name")
} else {
println(value.String())
}
2.7 判断JSON字符串是否合法的JSON

if !gjson.Valid(json) {
return errors.New("invalid json")
}
2.8 使用修饰符定制获取结果

gjson支持使用修饰符来定制元素获取结果,在搜索表达式中加上管道符和修饰符即可,比如`children|@reverse|1`表示children数组逆序之后的第二个元素(index为1的那个元素)。来看一下例子:
const json = `{
"name": {"first": "Tom", "last": "Anderson"},
"friends": [
{"first_name": "Dale", "last_name": "Murphy", "age": 44, "nets": ["ig", "fb", "tw"]},
{"first_name": "Roger", "last_name": "Craig", "age": 68, "nets": ["fb", "tw"]},
{"first_name": "Jane", "last_name": "Murphy", "age": 47, "nets": ["ig", "tw"]}
]
}`

func main() {
value := gjson.Get(json, "friends.#.first_name|@reverse") // 获取friends数组中所有元素对象的first_name属性,@reverse表示以逆序方式返回。
fmt.Println(value.String())
}
另外gjson还支持用户自定义修饰符,只需要调用gjson.AddModifier函数即可,例如:

gjson.AddModifier("case", func(json, arg string) string {
if arg == "upper" {
return strings.ToUpper(json)
}
if arg == "lower" {
return strings.ToLower(json)
}
return json
})
这样就给gjson增加了case修饰符,然后我就可以这样使用:

value := gjson.Get(json, "friends.#.first_name|@case:upper")
fmt.Println(value.String())
可以看到gjson的功能真是太强大。
————————————————
版权声明:本文为CSDN博主「程序猿架构」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/c315838651/article/details/105008314


有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

关注微信
3242 次点击
暂无回复
添加一条新回复 (您需要 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传

用户登录

没有账号?注册
(追記) (追記ここまで)

今日阅读排行

    加载中
(追記) (追記ここまで)

一周阅读排行

    加载中

关注我

  • 扫码关注领全套学习资料 关注微信公众号
  • 加入 QQ 群:
    • 192706294(已满)
    • 731990104(已满)
    • 798786647(已满)
    • 729884609(已满)
    • 977810755(已满)
    • 815126783(已满)
    • 812540095(已满)
    • 1006366459(已满)
    • 692541889

  • 关注微信公众号
  • 加入微信群:liuxiaoyan-s,备注入群
  • 也欢迎加入知识星球 Go粉丝们(免费)

给该专栏投稿 写篇新文章

每篇文章有总共有 5 次投稿机会

收入到我管理的专栏 新建专栏