...

Source file src/k8s.io/client-go/util/jsonpath/jsonpath.go

Documentation: k8s.io/client-go/util/jsonpath

     1  /*
     2  Copyright 2015 The Kubernetes Authors.
     3  
     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
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    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.
    15  */
    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  // New creates a new JSONPath with the given name.
    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  // AllowMissingKeys allows a caller to specify whether they want an error if a field or map key
    54  // cannot be located, or simply an empty result. The receiver is returned for chaining.
    55  func (j *JSONPath) AllowMissingKeys(allow bool) *JSONPath {
    56  	j.allowMissingKeys = allow
    57  	return j
    58  }
    59  
    60  // Parse parses the given template and returns an error.
    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  // Execute bounds data into template and writes the result.
    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  		// encounter an end node, break the current block
    97  		if j.endRange > 0 && j.endRange <= j.inRange {
    98  			j.endRange--
    99  			j.lastEndNode = &nodes[i]
   100  			break
   101  		}
   102  		// encounter a range node, start a range loop
   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  				// If the range has no results, we still need to process the nodes within the range
   117  				// so the position will advance to the end node
   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  			// Fast forward to resume processing after the most recent end node that was encountered
   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  // EnableJSONOutput changes the PrintResults behavior to return a JSON array of results
   141  func (j *JSONPath) EnableJSONOutput(v bool) {
   142  	j.outputJSON = v
   143  }
   144  
   145  // PrintResults writes the results into writer
   146  func (j *JSONPath) PrintResults(wr io.Writer, results []reflect.Value) error {
   147  	if j.outputJSON {
   148  		// convert the []reflect.Value to something that json
   149  		// will be able to marshal
   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  // walk visits tree rooted at the given node in DFS order
   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  // evalInt evaluates IntNode
   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  // evalFloat evaluates FloatNode
   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  // evalBool evaluates BoolNode
   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  // evalList evaluates ListNode
   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  // evalIdentifier evaluates IdentifierNode
   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  // evalArray evaluates ArrayNode
   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 { // if you're requesting zero elements, allow it through.
   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  // evalUnion evaluates UnionNode
   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  			// handle 'inline'
   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  // evalField evaluates field of struct or key of map.
   393  func (j *JSONPath) evalField(input []reflect.Value, node *FieldNode) ([]reflect.Value, error) {
   394  	results := []reflect.Value{}
   395  	// If there's no input, there's no output
   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  			// node value type must be convertible to map key type
   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  // evalWildcard extracts all contents of the given value
   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  // evalRecursive visits the given value recursively and pushes all of them to result
   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  // evalFilter filters array according to FilterNode
   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  			//case exists
   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  // evalToText translates reflect value to corresponding text
   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