3

json 二 开源库gjson的用法

 2 years ago
source link: https://studygolang.com/articles/35244
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

json 二 开源库gjson的用法

xiaojun1195 · 2天之前 · 133 次点击 · 预计阅读时间 4 分钟 · 大约8小时之前 开始浏览    

二 开源库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


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

280

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


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK