go language json parsing gjson

 3 minutes to read

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:

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