go语言json解析gjson

 阅读大约需要2分钟

go语言json解析gjson

go语言json解析无论是使用标准库encoding/json还是第三库json-iterator,都需要定义 结构体或者map,有的时候我们只想获取json中的部分值,定义结构体或者map还是比较麻烦的, 这时候我们可以选择gjson。

gjson是一个Go包,它提供了一种从json文档中获取值的快速简单的方法, 它具有单行检索、点符号路径、迭代和解析json行等功能。

开源代码地址: https://github.com/tidwall/gjson Star 10.4k

文档地址:https://pkg.go.dev/github.com/tidwall/gjson

安装 go get -u github.com/tidwall/gjson

要解析的json串如下:

{
  "name": {"first": "Tom", "last": "Anderson"},
  "age":37,
  "children": ["Sara","Alex","Jack"],
  "fav.movie": "Deer 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"]}
  ]
}

定义一个json串

const json = `{
  "name": {"first": "Tom", "last": "Anderson"},
  "age":37,
  "children": ["Sara","Alex","Jack"],
  "fav.movie": "Deer 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"]}
  ]
}`

校验是否是合法的json格式,代码如下:

if !gjson.Valid(json) {
	fmt.Println(errors.New("invalid json"))
}

使用name.last解析name中last的值

value := gjson.Get(json, "name.last")
	if !value.Exists() {
		println("no last name")
	} else {
		println(value.String())
}

运行结果如下:

Anderson

其他解析语法规则如下:

"name.last"          >> "Anderson"
"age"                >> 37
"children"           >> ["Sara","Alex","Jack"]
"children.#"         >> 3
"children.1"         >> "Alex"
"child*.2"           >> "Jack"
"c?ildren.0"         >> "Sara"
"fav\.movie"         >> "Deer Hunter"
"friends.#.first"    >> ["Dale","Roger","Jane"]
"friends.1.last"     >> "Craig"
friends.#(last=="Murphy").first    >> "Dale"
friends.#(last=="Murphy")#.first   >> ["Dale","Jane"]
friends.#(age>45)#.last            >> ["Craig","Murphy"]
friends.#(first%"D*").last         >> "Murphy"
friends.#(first!%"D*").last        >> "Craig"
friends.#(nets.#(=="fb"))#.first   >> ["Dale","Roger"]

json解析结果转为切片[]Result

result := gjson.Get(json, "friends.#.first")
for _, name := range result.Array() {
	println(name.String())
}

运行结果如下:

Dale
Roger
Jane

遍历切片

result1 := gjson.Get(json, "friends.#.first")
	result1.ForEach(func(key, value gjson.Result) bool {
		fmt.Println(key,value.String())
		return true // keep iterating
})

Parse(json)函数可以进行简单的解析,result.Get(path) 可以搜索结果。

例如下面的解析方式都将返回相同的结果:

gjson.Parse(json).Get("name").Get("last")
gjson.Get(json, "name").Get("last")
gjson.Get(json, "name.last")

通过下面方式可以将json解析为map

m, ok := gjson.Parse(json).Value().(map[string]any)
if !ok {
	// not a map
}

其中map[string]any,any类型为interface{}类型的别名,type any = interface{} 在go1.18中builtin.go中定义

gjson.GetMany函数可用于同时获取多个值

results := gjson.GetMany(json, "name.first", "name.last", "age")
fmt.Println(results)

运行结果如下:

[Tom Anderson 37]

上面完整代码如下:

package main

import (
	"errors"
	"fmt"
	"github.com/tidwall/gjson"
)

const json = `{
  "name": {"first": "Tom", "last": "Anderson"},
  "age":37,
  "children": ["Sara","Alex","Jack"],
  "fav.movie": "Deer 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"]}
  ]
}`

func main() {

	if !gjson.Valid(json) {
		fmt.Println(errors.New("invalid json"))
	}
	value := gjson.Get(json, "name.last")
	if !value.Exists() {
		println("no last name")
	} else {
		println(value.String())
	}

	value1 := gjson.Get(json, "children")
	fmt.Println(value1)

	results := gjson.GetMany(json, "name.first", "name.last", "age")
	fmt.Println(results)

	result := gjson.Get(json, "friends.#.first")
	for _, name := range result.Array() {
		println(name.String())
	}

	result1 := gjson.Get(json, "friends.#.first")
	result1.ForEach(func(key, value gjson.Result) bool {
		fmt.Println(key,value.String())
		return true // keep iterating
	})

	m, ok := gjson.Parse(json).Value().(map[string]any)
	if !ok {
		fmt.Println("not a map")
	}else {
		fmt.Println(m)
	}
}

更多使用方式访问:

https://github.com/tidwall/gjson/blob/master/README.md