/
get.go
137 lines (111 loc) · 3.32 KB
/
get.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
package ijson
// Get returns the result corresponding to provided path.
// If it fails to resolve the path, an error will be returned.
// Returns the same data if path is not provided, with nil error.
//
// Path syntax - Get(data, "#0", "friends", "#~name", "#")
//
// Explanation -
//
// "#0" - access the 0th element in the array
// "friends" - access the friends key from object
// "#~name" - return an array of all the objects having "name" field.
// "#" - return the length of the result array
//
func Get(data interface{}, path ...string) (interface{}, error) {
var err error
for i := range path {
switch pathType := DetectGetPath(path[i]); pathType {
case PGet_Obj:
data, err = GetObject(data, path[i])
case PGet_ArrIdx:
idx, idxErr := index(path[0], PGet_ArrIdx)
if idxErr != nil {
return nil, idxErr
}
data, err = GetArrayIndex(data, idx)
case PGet_ArrFld:
data, err = GetArrayField(data, field(path[i]))
case PGet_ArrLen:
return GetArrayLen(data)
case P_Unknown:
return nil, errInvPth
}
if err != nil {
return nil, err
}
}
return data, nil
}
// GetP is same as Get(). It just takes `"."` separated path.
//
// Path syntax - Get(data, "#0".friends".#~name".#")
//
// See Get() function for detailed explanation
func GetP(data interface{}, path string) (interface{}, error) {
return Get(data, split(path)...)
}
// GetObject returns the data against the provided field.
// It expects the input data to be an object with string key.
// An error will be returned if the input is not a valid `map[string]interface{}` OR field does not exists.
func GetObject(data interface{}, field string) (interface{}, error) {
object, exists := data.(map[string]interface{})
if !exists {
return nil, errExpObj
}
data, exists = object[field]
if !exists {
return nil, errNotFnd
}
return data, nil
}
// GetArrayIndex returns the data present at provided index.
// It expects the input data to be an array.
// An error will be returned if the input is not a valid `[]interface{}` OR index is out of range.
func GetArrayIndex(data interface{}, idx int) (interface{}, error) {
array, exists := data.([]interface{})
if !exists {
return nil, errExpArr
}
if idx < 0 || idx >= len(array) {
return nil, errOutBnd
}
return array[idx], nil
}
// GetArrayField returns all the objects matching the provided field.
// It expects the input data to be an array of objects.
// If provided data is array of values, it will return an empty array.
// An error will be returned if the input is not a valid `[]interface{}`.
func GetArrayField(data interface{}, field string) ([]interface{}, error) {
array, exists := data.([]interface{})
if !exists {
return nil, errExpArr
}
result := make([]interface{}, len(array))
var j, k int
for j = range array {
o, ok := array[j].(map[string]interface{})
if !ok {
continue
}
v, ok := o[field]
if ok {
result[k] = v
k++
}
}
return result[:k], nil
}
// GetArrayLen returns length of the array.
// It expects the input data to be an array OR nil. Length will be zero if data is nil.
// An error will be returned if the input is not nil and not a valid `[]interface{}`.
func GetArrayLen(data interface{}) (int, error) {
if data == nil {
return 0, nil
}
array, exists := data.([]interface{})
if !exists {
return 0, errExpArr
}
return len(array), nil
}