1
16
17 package jsonpath
18
19 import (
20 "bytes"
21 "encoding/json"
22 "fmt"
23 "io"
24 "reflect"
25 "strings"
26
27 "k8s.io/client-go/third_party/forked/golang/template"
28 )
29
30 type JSONPath struct {
31 name string
32 parser *Parser
33 beginRange int
34 inRange int
35 endRange int
36
37 lastEndNode *Node
38
39 allowMissingKeys bool
40 outputJSON bool
41 }
42
43
44 func New(name string) *JSONPath {
45 return &JSONPath{
46 name: name,
47 beginRange: 0,
48 inRange: 0,
49 endRange: 0,
50 }
51 }
52
53
54
55 func (j *JSONPath) AllowMissingKeys(allow bool) *JSONPath {
56 j.allowMissingKeys = allow
57 return j
58 }
59
60
61 func (j *JSONPath) Parse(text string) error {
62 var err error
63 j.parser, err = Parse(j.name, text)
64 return err
65 }
66
67
68 func (j *JSONPath) Execute(wr io.Writer, data interface{}) error {
69 fullResults, err := j.FindResults(data)
70 if err != nil {
71 return err
72 }
73 for ix := range fullResults {
74 if err := j.PrintResults(wr, fullResults[ix]); err != nil {
75 return err
76 }
77 }
78 return nil
79 }
80
81 func (j *JSONPath) FindResults(data interface{}) ([][]reflect.Value, error) {
82 if j.parser == nil {
83 return nil, fmt.Errorf("%s is an incomplete jsonpath template", j.name)
84 }
85
86 cur := []reflect.Value{reflect.ValueOf(data)}
87 nodes := j.parser.Root.Nodes
88 fullResult := [][]reflect.Value{}
89 for i := 0; i < len(nodes); i++ {
90 node := nodes[i]
91 results, err := j.walk(cur, node)
92 if err != nil {
93 return nil, err
94 }
95
96
97 if j.endRange > 0 && j.endRange <= j.inRange {
98 j.endRange--
99 j.lastEndNode = &nodes[i]
100 break
101 }
102
103 if j.beginRange > 0 {
104 j.beginRange--
105 j.inRange++
106 if len(results) > 0 {
107 for _, value := range results {
108 j.parser.Root.Nodes = nodes[i+1:]
109 nextResults, err := j.FindResults(value.Interface())
110 if err != nil {
111 return nil, err
112 }
113 fullResult = append(fullResult, nextResults...)
114 }
115 } else {
116
117
118 j.parser.Root.Nodes = nodes[i+1:]
119 _, err := j.FindResults(nil)
120 if err != nil {
121 return nil, err
122 }
123 }
124 j.inRange--
125
126
127 for k := i + 1; k < len(nodes); k++ {
128 if &nodes[k] == j.lastEndNode {
129 i = k
130 break
131 }
132 }
133 continue
134 }
135 fullResult = append(fullResult, results)
136 }
137 return fullResult, nil
138 }
139
140
141 func (j *JSONPath) EnableJSONOutput(v bool) {
142 j.outputJSON = v
143 }
144
145
146 func (j *JSONPath) PrintResults(wr io.Writer, results []reflect.Value) error {
147 if j.outputJSON {
148
149
150 r := make([]interface{}, 0, len(results))
151 for i := range results {
152 r = append(r, results[i].Interface())
153 }
154 results = []reflect.Value{reflect.ValueOf(r)}
155 }
156 for i, r := range results {
157 var text []byte
158 var err error
159 outputJSON := true
160 kind := r.Kind()
161 if kind == reflect.Interface {
162 kind = r.Elem().Kind()
163 }
164 switch kind {
165 case reflect.Map:
166 case reflect.Array:
167 case reflect.Slice:
168 case reflect.Struct:
169 default:
170 outputJSON = false
171 }
172 switch {
173 case outputJSON || j.outputJSON:
174 if j.outputJSON {
175 text, err = json.MarshalIndent(r.Interface(), "", " ")
176 text = append(text, '\n')
177 } else {
178 text, err = json.Marshal(r.Interface())
179 }
180 default:
181 text, err = j.evalToText(r)
182 }
183 if err != nil {
184 return err
185 }
186 if i != len(results)-1 {
187 text = append(text, ' ')
188 }
189 if _, err = wr.Write(text); err != nil {
190 return err
191 }
192 }
193
194 return nil
195
196 }
197
198
199 func (j *JSONPath) walk(value []reflect.Value, node Node) ([]reflect.Value, error) {
200 switch node := node.(type) {
201 case *ListNode:
202 return j.evalList(value, node)
203 case *TextNode:
204 return []reflect.Value{reflect.ValueOf(node.Text)}, nil
205 case *FieldNode:
206 return j.evalField(value, node)
207 case *ArrayNode:
208 return j.evalArray(value, node)
209 case *FilterNode:
210 return j.evalFilter(value, node)
211 case *IntNode:
212 return j.evalInt(value, node)
213 case *BoolNode:
214 return j.evalBool(value, node)
215 case *FloatNode:
216 return j.evalFloat(value, node)
217 case *WildcardNode:
218 return j.evalWildcard(value, node)
219 case *RecursiveNode:
220 return j.evalRecursive(value, node)
221 case *UnionNode:
222 return j.evalUnion(value, node)
223 case *IdentifierNode:
224 return j.evalIdentifier(value, node)
225 default:
226 return value, fmt.Errorf("unexpected Node %v", node)
227 }
228 }
229
230
231 func (j *JSONPath) evalInt(input []reflect.Value, node *IntNode) ([]reflect.Value, error) {
232 result := make([]reflect.Value, len(input))
233 for i := range input {
234 result[i] = reflect.ValueOf(node.Value)
235 }
236 return result, nil
237 }
238
239
240 func (j *JSONPath) evalFloat(input []reflect.Value, node *FloatNode) ([]reflect.Value, error) {
241 result := make([]reflect.Value, len(input))
242 for i := range input {
243 result[i] = reflect.ValueOf(node.Value)
244 }
245 return result, nil
246 }
247
248
249 func (j *JSONPath) evalBool(input []reflect.Value, node *BoolNode) ([]reflect.Value, error) {
250 result := make([]reflect.Value, len(input))
251 for i := range input {
252 result[i] = reflect.ValueOf(node.Value)
253 }
254 return result, nil
255 }
256
257
258 func (j *JSONPath) evalList(value []reflect.Value, node *ListNode) ([]reflect.Value, error) {
259 var err error
260 curValue := value
261 for _, node := range node.Nodes {
262 curValue, err = j.walk(curValue, node)
263 if err != nil {
264 return curValue, err
265 }
266 }
267 return curValue, nil
268 }
269
270
271 func (j *JSONPath) evalIdentifier(input []reflect.Value, node *IdentifierNode) ([]reflect.Value, error) {
272 results := []reflect.Value{}
273 switch node.Name {
274 case "range":
275 j.beginRange++
276 results = input
277 case "end":
278 if j.inRange > 0 {
279 j.endRange++
280 } else {
281 return results, fmt.Errorf("not in range, nothing to end")
282 }
283 default:
284 return input, fmt.Errorf("unrecognized identifier %v", node.Name)
285 }
286 return results, nil
287 }
288
289
290 func (j *JSONPath) evalArray(input []reflect.Value, node *ArrayNode) ([]reflect.Value, error) {
291 result := []reflect.Value{}
292 for _, value := range input {
293
294 value, isNil := template.Indirect(value)
295 if isNil {
296 continue
297 }
298 if value.Kind() != reflect.Array && value.Kind() != reflect.Slice {
299 return input, fmt.Errorf("%v is not array or slice", value.Type())
300 }
301 params := node.Params
302 if !params[0].Known {
303 params[0].Value = 0
304 }
305 if params[0].Value < 0 {
306 params[0].Value += value.Len()
307 }
308 if !params[1].Known {
309 params[1].Value = value.Len()
310 }
311
312 if params[1].Value < 0 || (params[1].Value == 0 && params[1].Derived) {
313 params[1].Value += value.Len()
314 }
315 sliceLength := value.Len()
316 if params[1].Value != params[0].Value {
317 if params[0].Value >= sliceLength || params[0].Value < 0 {
318 return input, fmt.Errorf("array index out of bounds: index %d, length %d", params[0].Value, sliceLength)
319 }
320 if params[1].Value > sliceLength || params[1].Value < 0 {
321 return input, fmt.Errorf("array index out of bounds: index %d, length %d", params[1].Value-1, sliceLength)
322 }
323 if params[0].Value > params[1].Value {
324 return input, fmt.Errorf("starting index %d is greater than ending index %d", params[0].Value, params[1].Value)
325 }
326 } else {
327 return result, nil
328 }
329
330 value = value.Slice(params[0].Value, params[1].Value)
331
332 step := 1
333 if params[2].Known {
334 if params[2].Value <= 0 {
335 return input, fmt.Errorf("step must be > 0")
336 }
337 step = params[2].Value
338 }
339 for i := 0; i < value.Len(); i += step {
340 result = append(result, value.Index(i))
341 }
342 }
343 return result, nil
344 }
345
346
347 func (j *JSONPath) evalUnion(input []reflect.Value, node *UnionNode) ([]reflect.Value, error) {
348 result := []reflect.Value{}
349 for _, listNode := range node.Nodes {
350 temp, err := j.evalList(input, listNode)
351 if err != nil {
352 return input, err
353 }
354 result = append(result, temp...)
355 }
356 return result, nil
357 }
358
359 func (j *JSONPath) findFieldInValue(value *reflect.Value, node *FieldNode) (reflect.Value, error) {
360 t := value.Type()
361 var inlineValue *reflect.Value
362 for ix := 0; ix < t.NumField(); ix++ {
363 f := t.Field(ix)
364 jsonTag := f.Tag.Get("json")
365 parts := strings.Split(jsonTag, ",")
366 if len(parts) == 0 {
367 continue
368 }
369 if parts[0] == node.Value {
370 return value.Field(ix), nil
371 }
372 if len(parts[0]) == 0 {
373 val := value.Field(ix)
374 inlineValue = &val
375 }
376 }
377 if inlineValue != nil {
378 if inlineValue.Kind() == reflect.Struct {
379
380 match, err := j.findFieldInValue(inlineValue, node)
381 if err != nil {
382 return reflect.Value{}, err
383 }
384 if match.IsValid() {
385 return match, nil
386 }
387 }
388 }
389 return value.FieldByName(node.Value), nil
390 }
391
392
393 func (j *JSONPath) evalField(input []reflect.Value, node *FieldNode) ([]reflect.Value, error) {
394 results := []reflect.Value{}
395
396 if len(input) == 0 {
397 return results, nil
398 }
399 for _, value := range input {
400 var result reflect.Value
401 value, isNil := template.Indirect(value)
402 if isNil {
403 continue
404 }
405
406 if value.Kind() == reflect.Struct {
407 var err error
408 if result, err = j.findFieldInValue(&value, node); err != nil {
409 return nil, err
410 }
411 } else if value.Kind() == reflect.Map {
412 mapKeyType := value.Type().Key()
413 nodeValue := reflect.ValueOf(node.Value)
414
415 if !nodeValue.Type().ConvertibleTo(mapKeyType) {
416 return results, fmt.Errorf("%s is not convertible to %s", nodeValue, mapKeyType)
417 }
418 result = value.MapIndex(nodeValue.Convert(mapKeyType))
419 }
420 if result.IsValid() {
421 results = append(results, result)
422 }
423 }
424 if len(results) == 0 {
425 if j.allowMissingKeys {
426 return results, nil
427 }
428 return results, fmt.Errorf("%s is not found", node.Value)
429 }
430 return results, nil
431 }
432
433
434 func (j *JSONPath) evalWildcard(input []reflect.Value, node *WildcardNode) ([]reflect.Value, error) {
435 results := []reflect.Value{}
436 for _, value := range input {
437 value, isNil := template.Indirect(value)
438 if isNil {
439 continue
440 }
441
442 kind := value.Kind()
443 if kind == reflect.Struct {
444 for i := 0; i < value.NumField(); i++ {
445 results = append(results, value.Field(i))
446 }
447 } else if kind == reflect.Map {
448 for _, key := range value.MapKeys() {
449 results = append(results, value.MapIndex(key))
450 }
451 } else if kind == reflect.Array || kind == reflect.Slice || kind == reflect.String {
452 for i := 0; i < value.Len(); i++ {
453 results = append(results, value.Index(i))
454 }
455 }
456 }
457 return results, nil
458 }
459
460
461 func (j *JSONPath) evalRecursive(input []reflect.Value, node *RecursiveNode) ([]reflect.Value, error) {
462 result := []reflect.Value{}
463 for _, value := range input {
464 results := []reflect.Value{}
465 value, isNil := template.Indirect(value)
466 if isNil {
467 continue
468 }
469
470 kind := value.Kind()
471 if kind == reflect.Struct {
472 for i := 0; i < value.NumField(); i++ {
473 results = append(results, value.Field(i))
474 }
475 } else if kind == reflect.Map {
476 for _, key := range value.MapKeys() {
477 results = append(results, value.MapIndex(key))
478 }
479 } else if kind == reflect.Array || kind == reflect.Slice || kind == reflect.String {
480 for i := 0; i < value.Len(); i++ {
481 results = append(results, value.Index(i))
482 }
483 }
484 if len(results) != 0 {
485 result = append(result, value)
486 output, err := j.evalRecursive(results, node)
487 if err != nil {
488 return result, err
489 }
490 result = append(result, output...)
491 }
492 }
493 return result, nil
494 }
495
496
497 func (j *JSONPath) evalFilter(input []reflect.Value, node *FilterNode) ([]reflect.Value, error) {
498 results := []reflect.Value{}
499 for _, value := range input {
500 value, _ = template.Indirect(value)
501
502 if value.Kind() != reflect.Array && value.Kind() != reflect.Slice {
503 return input, fmt.Errorf("%v is not array or slice and cannot be filtered", value)
504 }
505 for i := 0; i < value.Len(); i++ {
506 temp := []reflect.Value{value.Index(i)}
507 lefts, err := j.evalList(temp, node.Left)
508
509
510 if node.Operator == "exists" {
511 if len(lefts) > 0 {
512 results = append(results, value.Index(i))
513 }
514 continue
515 }
516
517 if err != nil {
518 return input, err
519 }
520
521 var left, right interface{}
522 switch {
523 case len(lefts) == 0:
524 continue
525 case len(lefts) > 1:
526 return input, fmt.Errorf("can only compare one element at a time")
527 }
528 left = lefts[0].Interface()
529
530 rights, err := j.evalList(temp, node.Right)
531 if err != nil {
532 return input, err
533 }
534 switch {
535 case len(rights) == 0:
536 continue
537 case len(rights) > 1:
538 return input, fmt.Errorf("can only compare one element at a time")
539 }
540 right = rights[0].Interface()
541
542 pass := false
543 switch node.Operator {
544 case "<":
545 pass, err = template.Less(left, right)
546 case ">":
547 pass, err = template.Greater(left, right)
548 case "==":
549 pass, err = template.Equal(left, right)
550 case "!=":
551 pass, err = template.NotEqual(left, right)
552 case "<=":
553 pass, err = template.LessEqual(left, right)
554 case ">=":
555 pass, err = template.GreaterEqual(left, right)
556 default:
557 return results, fmt.Errorf("unrecognized filter operator %s", node.Operator)
558 }
559 if err != nil {
560 return results, err
561 }
562 if pass {
563 results = append(results, value.Index(i))
564 }
565 }
566 }
567 return results, nil
568 }
569
570
571 func (j *JSONPath) evalToText(v reflect.Value) ([]byte, error) {
572 iface, ok := template.PrintableValue(v)
573 if !ok {
574 return nil, fmt.Errorf("can't print type %s", v.Type())
575 }
576 if iface == nil {
577 return []byte("null"), nil
578 }
579 var buffer bytes.Buffer
580 fmt.Fprint(&buffer, iface)
581 return buffer.Bytes(), nil
582 }
583
View as plain text