Nested Visiting
gjson
supports hierarchical retrieval access to data content, with the default hierarchical separator being ".". This feature makes it very convenient for developers to flexibly access unknown data structures.
Example 1, Basic Usage
func main() {
data :=
`{
"users" : {
"count" : 2,
"list" : [
{"name" : "Ming", "score" : 60},
{"name" : "John", "score" : 99.5}
]
}
}`
if j, err := gjson.DecodeToJson(data); err != nil {
panic(err)
} else {
fmt.Println("John Score:", j.Get("users.list.1.score"))
}
// Output:
// John Score: 99.5
}
As you can see, the gjson.Json
object can retrieve the corresponding variable information through very flexible hierarchical filtering functions ( j.GetFloat32("users.list.1.score")
).
Example 2, Custom Hierarchical Separator
func main() {
data :=
`{
"users" : {
"count" : 2,
"list" : [
{"name" : "Ming", "score" : 60},
{"name" : "John", "score" : 99.5}
]
}
}`
if j, err := gjson.DecodeToJson(data); err != nil {
panic(err)
} else {
j.SetSplitChar('#')
fmt.Println("John Score:", j.Get("users#list#1#score"))
}
// Output:
// John Score: 99.5
}
As you can see, we can set our custom separator using the SetSplitChar
method.
Example 3, Handling the Case Where Key Names Themselves Contain Hierarchical Symbols "."
func main() {
data :=
`{
"users" : {
"count" : 100
},
"users.count" : 101
}`
if j, err := gjson.DecodeToJson(data); err != nil {
glog.Error(gctx.New(), err)
} else {
j.SetViolenceCheck(true)
fmt.Println("Users Count:", j.Get("users.count"))
}
// Output:
// Users Count: 101
}
The result printed after running is 101
. When the key name contains ".", we can set conflict detection through SetViolenceCheck
, and the retrieval priority will follow: key name->hierarchical, so there won't be ambiguity. However, when the conflict detection switch is on, the retrieval efficiency will be lower, and it is off by default.
Precautions
As everyone knows, in Golang
, the map/slice
type is actually a "reference type" (also known as a "pointer type"), so when you modify the key-value/index items of this type of variable, it will also modify its corresponding underlying data.
For efficiency, the gjson
package does not make value copies for the data type when some retrieval methods return map/slice
, so when you modify the returned data, it will also modify the underlying data of gjson
.
For example:
func main() {
jsonContent := `{"map":{"key":"value"}, "slice":[59,90]}`
j, _ := gjson.LoadJson(jsonContent)
m := j.Get("map")
mMap := m.Map()
fmt.Println(mMap)
// Change the key-value pair.
mMap["key"] = "john"
// It changes the underlying key-value pair.
fmt.Println(j.Get("map").Map())
s := j.Get("slice")
sArray := s.Array()
fmt.Println(sArray)
// Change the value of specified index.
sArray[0] = 100
// It changes the underlying slice.
fmt.Println(j.Get("slice").Array())
// output:
// map[key:value]
// map[key:john]
// [59 90]
// [100 90]
}