github.com/nats-io/nsc/v2@v2.8.7-0.20240307184528-efd7023c6896/cmd/jsonpath.go (about) 1 /* 2 * Copyright 2020 The NATS Authors 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 package cmd 17 18 import ( 19 "encoding/json" 20 "fmt" 21 "strconv" 22 "strings" 23 ) 24 25 // Extracts a value from a JSON path - keys can be "name" or "person.name" or "persons[0].name" 26 func GetField(data []byte, jp string) ([]byte, error) { 27 m := make(map[string]interface{}) 28 if err := json.Unmarshal(data, &m); err != nil { 29 return nil, fmt.Errorf("error parsing json: %v", err) 30 } 31 var tokens []string 32 for _, v := range strings.Split(jp, ".") { 33 ob := strings.Index(v, "[") 34 if ob != -1 { 35 cb := strings.Index(v, "]") 36 if cb == -1 { 37 return nil, fmt.Errorf("bad path - unterminated index expression: %q in %q", v, jp) 38 } 39 n := v[:ob] 40 i := v[ob+1 : cb] 41 tokens = append(tokens, n, i) 42 } else { 43 tokens = append(tokens, v) 44 } 45 } 46 47 var d interface{} 48 d = m 49 for _, t := range tokens { 50 switch v := d.(type) { 51 case map[string]interface{}: 52 d = v[t] 53 case []interface{}: 54 idx, err := strconv.Atoi(t) 55 if err != nil { 56 return nil, fmt.Errorf("error parsing index: %q in %q", t, jp) 57 } 58 if idx > len(v) { 59 return nil, fmt.Errorf("index is out of bounds: %d in %q", idx, jp) 60 } 61 d = v[idx] 62 default: 63 return nil, fmt.Errorf("unable to extract %q in %q from %v", t, jp, v) 64 } 65 } 66 return json.Marshal(d) 67 }