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