...
1 package jsonpointer
2
3 import (
4 "reflect"
5 )
6
7
8 type JSONContainer interface {
9
10
11
12
13
14 JSONProp(prop string) interface{}
15 }
16
17
18
19 type JSONParent interface {
20
21
22
23
24 JSONProps() map[string]interface{}
25 }
26
27
28 func WalkJSON(tree interface{}, visit func(elem interface{}) error) error {
29 if tree == nil {
30 return nil
31 }
32
33 if err := visit(tree); err != nil {
34 return err
35 }
36
37 if con, ok := tree.(JSONParent); ok {
38 for _, ch := range con.JSONProps() {
39 if err := WalkJSON(ch, visit); err != nil {
40 return err
41 }
42 }
43 return nil
44 }
45
46
47 switch t := tree.(type) {
48 case map[string]interface{}:
49 for _, val := range t {
50 if err := WalkJSON(val, visit); err != nil {
51 return err
52 }
53 }
54 return nil
55 case []interface{}:
56 for _, val := range t {
57 if err := WalkJSON(val, visit); err != nil {
58 return err
59 }
60 }
61 return nil
62 }
63
64 return walkValue(reflect.ValueOf(tree), visit)
65 }
66
67 func walkValue(v reflect.Value, visit func(elem interface{}) error) error {
68 switch v.Kind() {
69 case reflect.Invalid:
70 return nil
71 case reflect.Ptr:
72 if !v.IsNil() {
73 walkValue(v.Elem(), visit)
74 }
75 case reflect.Map:
76 for _, key := range v.MapKeys() {
77 mi := v.MapIndex(key)
78 if mi.CanInterface() {
79 WalkJSON(mi.Interface(), visit)
80 }
81 }
82 case reflect.Struct:
83
84
85
86 for i := 0; i < v.NumField(); i++ {
87 f := v.Field(i)
88
89 if f.CanInterface() {
90 WalkJSON(f.Interface(), visit)
91 }
92 }
93 case reflect.Slice, reflect.Array:
94 for i := 0; i < v.Len(); i++ {
95 WalkJSON(v.Index(i).Interface(), visit)
96 }
97 }
98 return nil
99 }
100
View as plain text