@@ -12,7 +12,10 @@ import (
12
12
// Find position of next character which is not ' ', ',', '}' or ']'
13
13
func nextValue (data []byte ) int {
14
14
for i , c := range data {
15
- if c != ' ' && c != '\n' && c != '\r' && c != '\t' && c != ',' {
15
+ switch c {
16
+ case ' ' , '\n' , '\r' , '\t' , ',' :
17
+ continue
18
+ default :
16
19
return i
17
20
}
18
21
}
@@ -43,45 +46,33 @@ func stringEnd(data []byte) int {
43
46
44
47
// Find end of the data structure, array or object.
45
48
// For array openSym and closeSym will be '[' and ']', for object '{' and '}'
46
- // Know about nested structures
47
- func trailingBracket (data []byte , openSym byte , closeSym byte ) int {
49
+ func blockEnd (data []byte , openSym byte , closeSym byte ) int {
48
50
level := 0
49
51
i := 0
50
52
ln := len (data )
51
53
52
- for true {
53
- if i >= ln {
54
- return - 1
55
- }
56
-
57
- c := data [i ]
58
-
59
- // If inside string, skip it
60
- if c == '"' {
61
- //sFrom := i
62
- i ++
63
-
64
- se := stringEnd (data [i :])
54
+ for i < ln {
55
+ switch data [i ] {
56
+ case '"' : // If inside string, skip it
57
+ se := stringEnd (data [i + 1 :])
65
58
if se == - 1 {
66
59
return - 1
67
60
}
68
- i += se - 1
69
- }
70
-
71
- if c == openSym {
61
+ i += se
62
+ case openSym : // If open symbol, increase level
72
63
level ++
73
- } else if c == closeSym {
64
+ case closeSym : // If close symbol, increase level
74
65
level --
75
- }
76
66
77
- i ++
78
-
79
- if level == 0 {
80
- break
67
+ // If we have returned to the original level, we're done
68
+ if level == 0 {
69
+ return i + 1
70
+ }
81
71
}
72
+ i ++
82
73
}
83
74
84
- return i
75
+ return - 1
85
76
}
86
77
87
78
func searchKeys (data []byte , keys ... string ) int {
@@ -134,8 +125,8 @@ func searchKeys(data []byte, keys ...string) int {
134
125
level --
135
126
case '[' :
136
127
// Do not search for keys inside arrays
137
- aOff := trailingBracket (data [i :], '[' , ']' )
138
- i += aOff
128
+ arraySkip := blockEnd (data [i :], '[' , ']' )
129
+ i += arraySkip
139
130
}
140
131
141
132
i ++
@@ -169,7 +160,6 @@ Accept multiple keys to specify path to JSON value (in case of quering nested st
169
160
If no keys provided it will try to extract closest JSON value (simple ones or object/array), useful for reading streams or arrays, see `ArrayEach` implementation.
170
161
*/
171
162
func Get (data []byte , keys ... string ) (value []byte , dataType int , offset int , err error ) {
172
-
173
163
if len (keys ) > 0 {
174
164
if offset = searchKeys (data , keys ... ); offset == - 1 {
175
165
return []byte {}, NotExist , - 1 , errors .New ("Key path not found" )
@@ -198,7 +188,7 @@ func Get(data []byte, keys ...string) (value []byte, dataType int, offset int, e
198
188
} else if data [offset ] == '[' { // if array value
199
189
dataType = Array
200
190
// break label, for stopping nested loops
201
- endOffset = trailingBracket (data [offset :], '[' , ']' )
191
+ endOffset = blockEnd (data [offset :], '[' , ']' )
202
192
203
193
if endOffset == - 1 {
204
194
return []byte {}, dataType , offset , errors .New ("Value is array, but can't find closing ']' symbol" )
@@ -208,7 +198,7 @@ func Get(data []byte, keys ...string) (value []byte, dataType int, offset int, e
208
198
} else if data [offset ] == '{' { // if object value
209
199
dataType = Object
210
200
// break label, for stopping nested loops
211
- endOffset = trailingBracket (data [offset :], '{' , '}' )
201
+ endOffset = blockEnd (data [offset :], '{' , '}' )
212
202
213
203
if endOffset == - 1 {
214
204
return []byte {}, dataType , offset , errors .New ("Value looks like object, but can't find closing '}' symbol" )
0 commit comments