2 Copyright 2015 The Kubernetes Authors.
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
8 http://www.apache.org/licenses/LICENSE-2.0
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
26 "k8s.io/client-go/third_party/forked/golang/template"
29 type JSONPath struct {
32 stack [][]reflect.Value // push and pop values in different scopes
33 cur []reflect.Value // current scope values
41 // New creates a new JSONPath with the given name.
42 func New(name string) *JSONPath {
51 // AllowMissingKeys allows a caller to specify whether they want an error if a field or map key
52 // cannot be located, or simply an empty result. The receiver is returned for chaining.
53 func (j *JSONPath) AllowMissingKeys(allow bool) *JSONPath {
54 j.allowMissingKeys = allow
58 // Parse parses the given template and returns an error.
59 func (j *JSONPath) Parse(text string) error {
61 j.parser, err = Parse(j.name, text)
65 // Execute bounds data into template and writes the result.
66 func (j *JSONPath) Execute(wr io.Writer, data interface{}) error {
67 fullResults, err := j.FindResults(data)
71 for ix := range fullResults {
72 if err := j.PrintResults(wr, fullResults[ix]); err != nil {
79 func (j *JSONPath) FindResults(data interface{}) ([][]reflect.Value, error) {
81 return nil, fmt.Errorf("%s is an incomplete jsonpath template", j.name)
84 j.cur = []reflect.Value{reflect.ValueOf(data)}
85 nodes := j.parser.Root.Nodes
86 fullResult := [][]reflect.Value{}
87 for i := 0; i < len(nodes); i++ {
89 results, err := j.walk(j.cur, node)
94 // encounter an end node, break the current block
95 if j.endRange > 0 && j.endRange <= j.inRange {
99 // encounter a range node, start a range loop
100 if j.beginRange > 0 {
103 for k, value := range results {
104 j.parser.Root.Nodes = nodes[i+1:]
105 if k == len(results)-1 {
108 nextResults, err := j.FindResults(value.Interface())
112 fullResult = append(fullResult, nextResults...)
116 fullResult = append(fullResult, results)
118 return fullResult, nil
121 // PrintResults writes the results into writer
122 func (j *JSONPath) PrintResults(wr io.Writer, results []reflect.Value) error {
123 for i, r := range results {
124 text, err := j.evalToText(r)
128 if i != len(results)-1 {
129 text = append(text, ' ')
131 if _, err = wr.Write(text); err != nil {
138 // walk visits tree rooted at the given node in DFS order
139 func (j *JSONPath) walk(value []reflect.Value, node Node) ([]reflect.Value, error) {
140 switch node := node.(type) {
142 return j.evalList(value, node)
144 return []reflect.Value{reflect.ValueOf(node.Text)}, nil
146 return j.evalField(value, node)
148 return j.evalArray(value, node)
150 return j.evalFilter(value, node)
152 return j.evalInt(value, node)
154 return j.evalBool(value, node)
156 return j.evalFloat(value, node)
158 return j.evalWildcard(value, node)
160 return j.evalRecursive(value, node)
162 return j.evalUnion(value, node)
163 case *IdentifierNode:
164 return j.evalIdentifier(value, node)
166 return value, fmt.Errorf("unexpected Node %v", node)
170 // evalInt evaluates IntNode
171 func (j *JSONPath) evalInt(input []reflect.Value, node *IntNode) ([]reflect.Value, error) {
172 result := make([]reflect.Value, len(input))
173 for i := range input {
174 result[i] = reflect.ValueOf(node.Value)
179 // evalFloat evaluates FloatNode
180 func (j *JSONPath) evalFloat(input []reflect.Value, node *FloatNode) ([]reflect.Value, error) {
181 result := make([]reflect.Value, len(input))
182 for i := range input {
183 result[i] = reflect.ValueOf(node.Value)
188 // evalBool evaluates BoolNode
189 func (j *JSONPath) evalBool(input []reflect.Value, node *BoolNode) ([]reflect.Value, error) {
190 result := make([]reflect.Value, len(input))
191 for i := range input {
192 result[i] = reflect.ValueOf(node.Value)
197 // evalList evaluates ListNode
198 func (j *JSONPath) evalList(value []reflect.Value, node *ListNode) ([]reflect.Value, error) {
201 for _, node := range node.Nodes {
202 curValue, err = j.walk(curValue, node)
210 // evalIdentifier evaluates IdentifierNode
211 func (j *JSONPath) evalIdentifier(input []reflect.Value, node *IdentifierNode) ([]reflect.Value, error) {
212 results := []reflect.Value{}
215 j.stack = append(j.stack, j.cur)
219 if j.endRange < j.inRange { // inside a loop, break the current block
223 // the loop is about to end, pop value and continue the following execution
224 if len(j.stack) > 0 {
225 j.cur, j.stack = j.stack[len(j.stack)-1], j.stack[:len(j.stack)-1]
227 return results, fmt.Errorf("not in range, nothing to end")
230 return input, fmt.Errorf("unrecognized identifier %v", node.Name)
235 // evalArray evaluates ArrayNode
236 func (j *JSONPath) evalArray(input []reflect.Value, node *ArrayNode) ([]reflect.Value, error) {
237 result := []reflect.Value{}
238 for _, value := range input {
240 value, isNil := template.Indirect(value)
244 if value.Kind() != reflect.Array && value.Kind() != reflect.Slice {
245 return input, fmt.Errorf("%v is not array or slice", value.Type())
247 params := node.Params
248 if !params[0].Known {
251 if params[0].Value < 0 {
252 params[0].Value += value.Len()
254 if !params[1].Known {
255 params[1].Value = value.Len()
258 if params[1].Value < 0 {
259 params[1].Value += value.Len()
262 sliceLength := value.Len()
263 if params[1].Value != params[0].Value { // if you're requesting zero elements, allow it through.
264 if params[0].Value >= sliceLength || params[0].Value < 0 {
265 return input, fmt.Errorf("array index out of bounds: index %d, length %d", params[0].Value, sliceLength)
267 if params[1].Value > sliceLength || params[1].Value < 0 {
268 return input, fmt.Errorf("array index out of bounds: index %d, length %d", params[1].Value-1, sliceLength)
272 if !params[2].Known {
273 value = value.Slice(params[0].Value, params[1].Value)
275 value = value.Slice3(params[0].Value, params[1].Value, params[2].Value)
277 for i := 0; i < value.Len(); i++ {
278 result = append(result, value.Index(i))
284 // evalUnion evaluates UnionNode
285 func (j *JSONPath) evalUnion(input []reflect.Value, node *UnionNode) ([]reflect.Value, error) {
286 result := []reflect.Value{}
287 for _, listNode := range node.Nodes {
288 temp, err := j.evalList(input, listNode)
292 result = append(result, temp...)
297 func (j *JSONPath) findFieldInValue(value *reflect.Value, node *FieldNode) (reflect.Value, error) {
299 var inlineValue *reflect.Value
300 for ix := 0; ix < t.NumField(); ix++ {
302 jsonTag := f.Tag.Get("json")
303 parts := strings.Split(jsonTag, ",")
307 if parts[0] == node.Value {
308 return value.Field(ix), nil
310 if len(parts[0]) == 0 {
311 val := value.Field(ix)
315 if inlineValue != nil {
316 if inlineValue.Kind() == reflect.Struct {
318 match, err := j.findFieldInValue(inlineValue, node)
320 return reflect.Value{}, err
327 return value.FieldByName(node.Value), nil
330 // evalField evaluates field of struct or key of map.
331 func (j *JSONPath) evalField(input []reflect.Value, node *FieldNode) ([]reflect.Value, error) {
332 results := []reflect.Value{}
333 // If there's no input, there's no output
337 for _, value := range input {
338 var result reflect.Value
339 value, isNil := template.Indirect(value)
344 if value.Kind() == reflect.Struct {
346 if result, err = j.findFieldInValue(&value, node); err != nil {
349 } else if value.Kind() == reflect.Map {
350 mapKeyType := value.Type().Key()
351 nodeValue := reflect.ValueOf(node.Value)
352 // node value type must be convertible to map key type
353 if !nodeValue.Type().ConvertibleTo(mapKeyType) {
354 return results, fmt.Errorf("%s is not convertible to %s", nodeValue, mapKeyType)
356 result = value.MapIndex(nodeValue.Convert(mapKeyType))
358 if result.IsValid() {
359 results = append(results, result)
362 if len(results) == 0 {
363 if j.allowMissingKeys {
366 return results, fmt.Errorf("%s is not found", node.Value)
371 // evalWildcard extracts all contents of the given value
372 func (j *JSONPath) evalWildcard(input []reflect.Value, node *WildcardNode) ([]reflect.Value, error) {
373 results := []reflect.Value{}
374 for _, value := range input {
375 value, isNil := template.Indirect(value)
381 if kind == reflect.Struct {
382 for i := 0; i < value.NumField(); i++ {
383 results = append(results, value.Field(i))
385 } else if kind == reflect.Map {
386 for _, key := range value.MapKeys() {
387 results = append(results, value.MapIndex(key))
389 } else if kind == reflect.Array || kind == reflect.Slice || kind == reflect.String {
390 for i := 0; i < value.Len(); i++ {
391 results = append(results, value.Index(i))
398 // evalRecursive visits the given value recursively and pushes all of them to result
399 func (j *JSONPath) evalRecursive(input []reflect.Value, node *RecursiveNode) ([]reflect.Value, error) {
400 result := []reflect.Value{}
401 for _, value := range input {
402 results := []reflect.Value{}
403 value, isNil := template.Indirect(value)
409 if kind == reflect.Struct {
410 for i := 0; i < value.NumField(); i++ {
411 results = append(results, value.Field(i))
413 } else if kind == reflect.Map {
414 for _, key := range value.MapKeys() {
415 results = append(results, value.MapIndex(key))
417 } else if kind == reflect.Array || kind == reflect.Slice || kind == reflect.String {
418 for i := 0; i < value.Len(); i++ {
419 results = append(results, value.Index(i))
422 if len(results) != 0 {
423 result = append(result, value)
424 output, err := j.evalRecursive(results, node)
428 result = append(result, output...)
434 // evalFilter filters array according to FilterNode
435 func (j *JSONPath) evalFilter(input []reflect.Value, node *FilterNode) ([]reflect.Value, error) {
436 results := []reflect.Value{}
437 for _, value := range input {
438 value, _ = template.Indirect(value)
440 if value.Kind() != reflect.Array && value.Kind() != reflect.Slice {
441 return input, fmt.Errorf("%v is not array or slice and cannot be filtered", value)
443 for i := 0; i < value.Len(); i++ {
444 temp := []reflect.Value{value.Index(i)}
445 lefts, err := j.evalList(temp, node.Left)
448 if node.Operator == "exists" {
450 results = append(results, value.Index(i))
459 var left, right interface{}
461 case len(lefts) == 0:
464 return input, fmt.Errorf("can only compare one element at a time")
466 left = lefts[0].Interface()
468 rights, err := j.evalList(temp, node.Right)
473 case len(rights) == 0:
475 case len(rights) > 1:
476 return input, fmt.Errorf("can only compare one element at a time")
478 right = rights[0].Interface()
481 switch node.Operator {
483 pass, err = template.Less(left, right)
485 pass, err = template.Greater(left, right)
487 pass, err = template.Equal(left, right)
489 pass, err = template.NotEqual(left, right)
491 pass, err = template.LessEqual(left, right)
493 pass, err = template.GreaterEqual(left, right)
495 return results, fmt.Errorf("unrecognized filter operator %s", node.Operator)
501 results = append(results, value.Index(i))
508 // evalToText translates reflect value to corresponding text
509 func (j *JSONPath) evalToText(v reflect.Value) ([]byte, error) {
510 iface, ok := template.PrintableValue(v)
512 return nil, fmt.Errorf("can't print type %s", v.Type())
514 var buffer bytes.Buffer
515 fmt.Fprint(&buffer, iface)
516 return buffer.Bytes(), nil