package json import ( "fmt" "strconv" "strings" ) func Query(parent Node, path []string) (Node, error) { if len(path) == 0 { return parent, nil } head, rest := path[0], path[1:] switch parent := parent.(type) { case ObjectNode: next, ok := parent.GetByKey(head) if !ok { return nil, fmt.Errorf("key %s not found at object %v", head, parent) } return Query(next, rest) case ArrayNode: stringIdx := strings.Trim(head, "[]") idx, err := strconv.Atoi(stringIdx) if err != nil { return nil, fmt.Errorf("key %s is invalid index: %w", stringIdx, err) } if idx >= parent.Len() { return nil, fmt.Errorf("index %d is out of range (len=%d)", idx, parent.Len()) } next := parent.Index(idx) return Query(next, rest) default: return nil, fmt.Errorf("can't get key=%s from node type = %t", head, parent) } } func MustQuery(parent Node, path []string) Node { n, err := Query(parent, path) if err != nil { panic(err) } return n }