interpreter.go (10508B)
1 package jmespath 2 3 import ( 4 "errors" 5 "reflect" 6 "unicode" 7 "unicode/utf8" 8 ) 9 10 /* This is a tree based interpreter. It walks the AST and directly 11 interprets the AST to search through a JSON document. 12 */ 13 14 type treeInterpreter struct { 15 fCall *functionCaller 16 } 17 18 func newInterpreter() *treeInterpreter { 19 interpreter := treeInterpreter{} 20 interpreter.fCall = newFunctionCaller() 21 return &interpreter 22 } 23 24 type expRef struct { 25 ref ASTNode 26 } 27 28 // Execute takes an ASTNode and input data and interprets the AST directly. 29 // It will produce the result of applying the JMESPath expression associated 30 // with the ASTNode to the input data "value". 31 func (intr *treeInterpreter) Execute(node ASTNode, value interface{}) (interface{}, error) { 32 switch node.nodeType { 33 case ASTComparator: 34 left, err := intr.Execute(node.children[0], value) 35 if err != nil { 36 return nil, err 37 } 38 right, err := intr.Execute(node.children[1], value) 39 if err != nil { 40 return nil, err 41 } 42 switch node.value { 43 case tEQ: 44 return objsEqual(left, right), nil 45 case tNE: 46 return !objsEqual(left, right), nil 47 } 48 leftNum, ok := left.(float64) 49 if !ok { 50 return nil, nil 51 } 52 rightNum, ok := right.(float64) 53 if !ok { 54 return nil, nil 55 } 56 switch node.value { 57 case tGT: 58 return leftNum > rightNum, nil 59 case tGTE: 60 return leftNum >= rightNum, nil 61 case tLT: 62 return leftNum < rightNum, nil 63 case tLTE: 64 return leftNum <= rightNum, nil 65 } 66 case ASTExpRef: 67 return expRef{ref: node.children[0]}, nil 68 case ASTFunctionExpression: 69 resolvedArgs := []interface{}{} 70 for _, arg := range node.children { 71 current, err := intr.Execute(arg, value) 72 if err != nil { 73 return nil, err 74 } 75 resolvedArgs = append(resolvedArgs, current) 76 } 77 return intr.fCall.CallFunction(node.value.(string), resolvedArgs, intr) 78 case ASTField: 79 if m, ok := value.(map[string]interface{}); ok { 80 key := node.value.(string) 81 return m[key], nil 82 } 83 return intr.fieldFromStruct(node.value.(string), value) 84 case ASTFilterProjection: 85 left, err := intr.Execute(node.children[0], value) 86 if err != nil { 87 return nil, nil 88 } 89 sliceType, ok := left.([]interface{}) 90 if !ok { 91 if isSliceType(left) { 92 return intr.filterProjectionWithReflection(node, left) 93 } 94 return nil, nil 95 } 96 compareNode := node.children[2] 97 collected := []interface{}{} 98 for _, element := range sliceType { 99 result, err := intr.Execute(compareNode, element) 100 if err != nil { 101 return nil, err 102 } 103 if !isFalse(result) { 104 current, err := intr.Execute(node.children[1], element) 105 if err != nil { 106 return nil, err 107 } 108 if current != nil { 109 collected = append(collected, current) 110 } 111 } 112 } 113 return collected, nil 114 case ASTFlatten: 115 left, err := intr.Execute(node.children[0], value) 116 if err != nil { 117 return nil, nil 118 } 119 sliceType, ok := left.([]interface{}) 120 if !ok { 121 // If we can't type convert to []interface{}, there's 122 // a chance this could still work via reflection if we're 123 // dealing with user provided types. 124 if isSliceType(left) { 125 return intr.flattenWithReflection(left) 126 } 127 return nil, nil 128 } 129 flattened := []interface{}{} 130 for _, element := range sliceType { 131 if elementSlice, ok := element.([]interface{}); ok { 132 flattened = append(flattened, elementSlice...) 133 } else if isSliceType(element) { 134 reflectFlat := []interface{}{} 135 v := reflect.ValueOf(element) 136 for i := 0; i < v.Len(); i++ { 137 reflectFlat = append(reflectFlat, v.Index(i).Interface()) 138 } 139 flattened = append(flattened, reflectFlat...) 140 } else { 141 flattened = append(flattened, element) 142 } 143 } 144 return flattened, nil 145 case ASTIdentity, ASTCurrentNode: 146 return value, nil 147 case ASTIndex: 148 if sliceType, ok := value.([]interface{}); ok { 149 index := node.value.(int) 150 if index < 0 { 151 index += len(sliceType) 152 } 153 if index < len(sliceType) && index >= 0 { 154 return sliceType[index], nil 155 } 156 return nil, nil 157 } 158 // Otherwise try via reflection. 159 rv := reflect.ValueOf(value) 160 if rv.Kind() == reflect.Slice { 161 index := node.value.(int) 162 if index < 0 { 163 index += rv.Len() 164 } 165 if index < rv.Len() && index >= 0 { 166 v := rv.Index(index) 167 return v.Interface(), nil 168 } 169 } 170 return nil, nil 171 case ASTKeyValPair: 172 return intr.Execute(node.children[0], value) 173 case ASTLiteral: 174 return node.value, nil 175 case ASTMultiSelectHash: 176 if value == nil { 177 return nil, nil 178 } 179 collected := make(map[string]interface{}) 180 for _, child := range node.children { 181 current, err := intr.Execute(child, value) 182 if err != nil { 183 return nil, err 184 } 185 key := child.value.(string) 186 collected[key] = current 187 } 188 return collected, nil 189 case ASTMultiSelectList: 190 if value == nil { 191 return nil, nil 192 } 193 collected := []interface{}{} 194 for _, child := range node.children { 195 current, err := intr.Execute(child, value) 196 if err != nil { 197 return nil, err 198 } 199 collected = append(collected, current) 200 } 201 return collected, nil 202 case ASTOrExpression: 203 matched, err := intr.Execute(node.children[0], value) 204 if err != nil { 205 return nil, err 206 } 207 if isFalse(matched) { 208 matched, err = intr.Execute(node.children[1], value) 209 if err != nil { 210 return nil, err 211 } 212 } 213 return matched, nil 214 case ASTAndExpression: 215 matched, err := intr.Execute(node.children[0], value) 216 if err != nil { 217 return nil, err 218 } 219 if isFalse(matched) { 220 return matched, nil 221 } 222 return intr.Execute(node.children[1], value) 223 case ASTNotExpression: 224 matched, err := intr.Execute(node.children[0], value) 225 if err != nil { 226 return nil, err 227 } 228 if isFalse(matched) { 229 return true, nil 230 } 231 return false, nil 232 case ASTPipe: 233 result := value 234 var err error 235 for _, child := range node.children { 236 result, err = intr.Execute(child, result) 237 if err != nil { 238 return nil, err 239 } 240 } 241 return result, nil 242 case ASTProjection: 243 left, err := intr.Execute(node.children[0], value) 244 if err != nil { 245 return nil, err 246 } 247 sliceType, ok := left.([]interface{}) 248 if !ok { 249 if isSliceType(left) { 250 return intr.projectWithReflection(node, left) 251 } 252 return nil, nil 253 } 254 collected := []interface{}{} 255 var current interface{} 256 for _, element := range sliceType { 257 current, err = intr.Execute(node.children[1], element) 258 if err != nil { 259 return nil, err 260 } 261 if current != nil { 262 collected = append(collected, current) 263 } 264 } 265 return collected, nil 266 case ASTSubexpression, ASTIndexExpression: 267 left, err := intr.Execute(node.children[0], value) 268 if err != nil { 269 return nil, err 270 } 271 return intr.Execute(node.children[1], left) 272 case ASTSlice: 273 sliceType, ok := value.([]interface{}) 274 if !ok { 275 if isSliceType(value) { 276 return intr.sliceWithReflection(node, value) 277 } 278 return nil, nil 279 } 280 parts := node.value.([]*int) 281 sliceParams := make([]sliceParam, 3) 282 for i, part := range parts { 283 if part != nil { 284 sliceParams[i].Specified = true 285 sliceParams[i].N = *part 286 } 287 } 288 return slice(sliceType, sliceParams) 289 case ASTValueProjection: 290 left, err := intr.Execute(node.children[0], value) 291 if err != nil { 292 return nil, nil 293 } 294 mapType, ok := left.(map[string]interface{}) 295 if !ok { 296 return nil, nil 297 } 298 values := make([]interface{}, len(mapType)) 299 for _, value := range mapType { 300 values = append(values, value) 301 } 302 collected := []interface{}{} 303 for _, element := range values { 304 current, err := intr.Execute(node.children[1], element) 305 if err != nil { 306 return nil, err 307 } 308 if current != nil { 309 collected = append(collected, current) 310 } 311 } 312 return collected, nil 313 } 314 return nil, errors.New("Unknown AST node: " + node.nodeType.String()) 315 } 316 317 func (intr *treeInterpreter) fieldFromStruct(key string, value interface{}) (interface{}, error) { 318 rv := reflect.ValueOf(value) 319 first, n := utf8.DecodeRuneInString(key) 320 fieldName := string(unicode.ToUpper(first)) + key[n:] 321 if rv.Kind() == reflect.Struct { 322 v := rv.FieldByName(fieldName) 323 if !v.IsValid() { 324 return nil, nil 325 } 326 return v.Interface(), nil 327 } else if rv.Kind() == reflect.Ptr { 328 // Handle multiple levels of indirection? 329 if rv.IsNil() { 330 return nil, nil 331 } 332 rv = rv.Elem() 333 v := rv.FieldByName(fieldName) 334 if !v.IsValid() { 335 return nil, nil 336 } 337 return v.Interface(), nil 338 } 339 return nil, nil 340 } 341 342 func (intr *treeInterpreter) flattenWithReflection(value interface{}) (interface{}, error) { 343 v := reflect.ValueOf(value) 344 flattened := []interface{}{} 345 for i := 0; i < v.Len(); i++ { 346 element := v.Index(i).Interface() 347 if reflect.TypeOf(element).Kind() == reflect.Slice { 348 // Then insert the contents of the element 349 // slice into the flattened slice, 350 // i.e flattened = append(flattened, mySlice...) 351 elementV := reflect.ValueOf(element) 352 for j := 0; j < elementV.Len(); j++ { 353 flattened = append( 354 flattened, elementV.Index(j).Interface()) 355 } 356 } else { 357 flattened = append(flattened, element) 358 } 359 } 360 return flattened, nil 361 } 362 363 func (intr *treeInterpreter) sliceWithReflection(node ASTNode, value interface{}) (interface{}, error) { 364 v := reflect.ValueOf(value) 365 parts := node.value.([]*int) 366 sliceParams := make([]sliceParam, 3) 367 for i, part := range parts { 368 if part != nil { 369 sliceParams[i].Specified = true 370 sliceParams[i].N = *part 371 } 372 } 373 final := []interface{}{} 374 for i := 0; i < v.Len(); i++ { 375 element := v.Index(i).Interface() 376 final = append(final, element) 377 } 378 return slice(final, sliceParams) 379 } 380 381 func (intr *treeInterpreter) filterProjectionWithReflection(node ASTNode, value interface{}) (interface{}, error) { 382 compareNode := node.children[2] 383 collected := []interface{}{} 384 v := reflect.ValueOf(value) 385 for i := 0; i < v.Len(); i++ { 386 element := v.Index(i).Interface() 387 result, err := intr.Execute(compareNode, element) 388 if err != nil { 389 return nil, err 390 } 391 if !isFalse(result) { 392 current, err := intr.Execute(node.children[1], element) 393 if err != nil { 394 return nil, err 395 } 396 if current != nil { 397 collected = append(collected, current) 398 } 399 } 400 } 401 return collected, nil 402 } 403 404 func (intr *treeInterpreter) projectWithReflection(node ASTNode, value interface{}) (interface{}, error) { 405 collected := []interface{}{} 406 v := reflect.ValueOf(value) 407 for i := 0; i < v.Len(); i++ { 408 element := v.Index(i).Interface() 409 result, err := intr.Execute(node.children[1], element) 410 if err != nil { 411 return nil, err 412 } 413 if result != nil { 414 collected = append(collected, result) 415 } 416 } 417 return collected, nil 418 }