层级访问

gjson支持对数据内容进行层级检索访问,层级分隔符号默认为”.“。该特性使得开发者可以灵活访问未知的数据结构内容变得非常简便。

示例1,基本使用

  1. func main() {
  2. data :=
  3. `{
  4. "users" : {
  5. "count" : 2,
  6. "list" : [
  7. {"name" : "Ming", "score" : 60},
  8. {"name" : "John", "score" : 99.5}
  9. ]
  10. }
  11. }`
  12. if j, err := gjson.DecodeToJson(data); err != nil {
  13. panic(err)
  14. } else {
  15. fmt.Println("John Score:", j.Get("users.list.1.score"))
  16. }
  17. // Output:
  18. // John Score: 99.5
  19. }

可以看到,gjson.Json对象可以通过非常灵活的层级筛选功能(j.GetFloat32("users.list.1.score"))检索到对应的变量信息。

示例2,自定义层级分隔符号

  1. func main() {
  2. data :=
  3. `{
  4. "users" : {
  5. "count" : 2,
  6. "list" : [
  7. {"name" : "Ming", "score" : 60},
  8. {"name" : "John", "score" : 99.5}
  9. ]
  10. }
  11. }`
  12. if j, err := gjson.DecodeToJson(data); err != nil {
  13. panic(err)
  14. } else {
  15. j.SetSplitChar('#')
  16. fmt.Println("John Score:", j.Get("users#list#1#score"))
  17. }
  18. // Output:
  19. // John Score: 99.5
  20. }

可以看到,我们可以通过SetSplitChar方法设置我们自定义的分隔符号。

示例3,处理键名本身带有层级符号”.“的情况

  1. func main() {
  2. data :=
  3. `{
  4. "users" : {
  5. "count" : 100
  6. },
  7. "users.count" : 101
  8. }`
  9. if j, err := gjson.DecodeToJson(data); err != nil {
  10. glog.Error(gctx.New(), err)
  11. } else {
  12. j.SetViolenceCheck(true)
  13. fmt.Println("Users Count:", j.Get("users.count"))
  14. }
  15. // Output:
  16. // John Score: 99.5
  17. }

运行之后打印出的结果为101。当键名存在”.“号时,我们可以通过SetViolenceCheck设置冲突检测,随后检索优先级将会按照:键名->层级,便并不会引起歧义。但是当冲突检测开关开启时,检索效率将会变低,默认为关闭状态。

注意事项

大家都知道,在Golang里面,map/slice类型其实是一个”引用类型”(也叫”指针类型”),因此当你对这种类型的变量 键值对/索引项 进行修改时,会同时修改到其对应的底层数据。

从效率上考虑,gjson包某些获取方法返回的数据类型为map/slice时,没有对齐做值拷贝,因此当你对返回的数据进行修改时,会同时修改gjson对应的底层数据。

例如:

  1. func main() {
  2. jsonContent := `{"map":{"key":"value"}, "slice":[59,90]}`
  3. j, _ := gjson.LoadJson(jsonContent)
  4. m := j.Get("map")
  5. mMap := m.Map()
  6. fmt.Println(mMap)
  7. // Change the key-value pair.
  8. mMap["key"] = "john"
  9. // It changes the underlying key-value pair.
  10. fmt.Println(j.Get("map").Map())
  11. s := j.Get("slice")
  12. sArray := s.Array()
  13. fmt.Println(sArray)
  14. // Change the value of specified index.
  15. sArray[0] = 100
  16. // It changes the underlying slice.
  17. fmt.Println(j.Get("slice").Array())
  18. // output:
  19. // map[key:value]
  20. // map[key:john]
  21. // [59 90]
  22. // [100 90]
  23. }