go language json parsing gjson
Go language json parsing needs to be defined whether using the standard library encoding/json or the third library json-iterator Structure or map, sometimes we only want to get part of the value in json, it is more troublesome to define structure or map, At this time we can choose gjson.
gjson is a Go package that provides a fast and easy way to get values from json documents, It has features like single line retrieval, dot notation paths, iteration and parsing of json lines.
Open source code address: https://github.com/tidwall/gjson Star 10.4k
Document address: https://pkg.go.dev/github.com/tidwall/gjson
Install go get -u github.com/tidwall/gjson
The json string to be parsed is as follows:
{
"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"]}
]
}
define a json string
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"]}
]
}`
To check whether it is a valid json format, the code is as follows:
if !gjson.Valid(json) {
fmt.Println(errors.New("invalid json"))
}
Use name.last to parse the value of last in name
value := gjson.Get(json, "name.last")
if !value.Exists() {
println("no last name")
} else {
println(value.String())
}
The results are as follows:
Anderson
Other parsing grammar rules are as follows:
"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"]
The json parsing result is converted into a slice []Result
result := gjson.Get(json, "friends.#.first")
for _, name := range result.Array() {
println(name.String())
}
The results are as follows:
Dale
Roger
Jane
iterate over slices
result1 := gjson.Get(json, "friends.#.first")
result1.ForEach(func(key, value gjson.Result) bool {
fmt.Println(key,value.String())
return true // keep iterating
})
The Parse(json) function can perform simple parsing, and result.Get(path) can search for results.
For example, the following parsing methods will all return the same result:
gjson.Parse(json).Get("name").Get("last")
gjson.Get(json, "name").Get("last")
gjson.Get(json, "name.last")
JSON can be parsed into map in the following way
m, ok := gjson.Parse(json).Value().(map[string]any)
if !ok {
// not a map
}
Where map[string]any, any type is an alias of interface{} type, type any = interface{}
is defined in builtin.go in go1.18
The gjson.GetMany function can be used to get multiple values at the same time
results := gjson.GetMany(json, "name.first", "name.last", "age")
fmt.Println(results)
The results are as follows:
[Tom Anderson 37]
The complete code above is as follows:
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)
}
}
For more usage visit: