func displayAsJson(v interface{}, jsonPath string) (err error) { marshalled, err := json.Marshal(v) if err != nil { return err } // a convenient special case if "$" == jsonPath { fmt.Printf("%s", string(marshalled)) return nil } paths, err := jsonpath.ParsePaths(jsonPath) if err != nil { return err } eval, err := jsonpath.EvalPathsInBytes(marshalled, paths) if err != nil { return err } for { if result, ok := eval.Next(); ok { fmt.Print(result.Pretty(false)) // true -> show keys in pretty string } else { break } } if eval.Error != nil { return eval.Error } return nil }
/** * If the httpAction specifies a Jsonpath in the Response, try to extract value(s) * from the responseBody. * * TODO extract both Jsonpath handling and Xmlpath handling into separate functions, and write tests for them. * * Uses github.com/NodePrime/jsonpath */ func processResult(httpAction HttpAction, sessionMap map[string]string, responseBody []byte) { if httpAction.ResponseHandler.Jsonpath != "" { paths, err := jsonpath.ParsePaths(httpAction.ResponseHandler.Jsonpath) if err != nil { panic(err) } eval, err := jsonpath.EvalPathsInBytes(responseBody, paths) if err != nil { panic(err) } // TODO optimization: Don't reinitialize each time, reuse this somehow. resultsArray := make([]string, 0, 10) for { if result, ok := eval.Next(); ok { value := strings.TrimSpace(result.Pretty(false)) resultsArray = append(resultsArray, trimChar(value, '"')) } else { break } } if eval.Error != nil { panic(eval.Error) } passResultIntoSessionMap(resultsArray, httpAction, sessionMap) } if httpAction.ResponseHandler.Xmlpath != "" { path := xmlpath.MustCompile(httpAction.ResponseHandler.Xmlpath) r := bytes.NewReader(responseBody) root, err := xmlpath.Parse(r) if err != nil { log.Fatal(err) } iterator := path.Iter(root) hasNext := iterator.Next() if hasNext { resultsArray := make([]string, 0, 10) for { if hasNext { node := iterator.Node() resultsArray = append(resultsArray, node.String()) hasNext = iterator.Next() } else { break } } passResultIntoSessionMap(resultsArray, httpAction, sessionMap) } } // log.Println(string(responseBody)) }
// Formats response func (c *Proxy) formatResponse(user *commons.User, response []byte) (string, error) { t, err := template.New("Service Template").Funcs(FuncMap).Parse(c.cfg.Response) if err != nil { return "", err } params := map[string]interface{}{} for name, selector := range c.cfg.Params { // Parse JsonPath expression paths, err := jsonpath.ParsePaths(selector) if err != nil { return "", err } // Eval JsonPath expression eval, err := jsonpath.EvalPathsInBytes(response, paths) if err != nil { return "", err } // Find matches var result *jsonpath.Result for { if try, ok := eval.Next(); ok { result = try } else { break } } if result != nil { param := string(result.Value) // Workaround for lexer strings if result.Type == jsonpath.JsonString { param = param[1 : len(param)-1] } params[name] = param } } // Override params params["username"] = user.Username params["nickname"] = user.Nickname // Execute template to string doc := bytes.Buffer{} err = t.Execute(&doc, params) if err != nil { return "", err } return doc.String(), nil }
func main() { var pathStrings pathSlice filePtr := flag.StringP("file", "f", "", "Path to json file") jsonPtr := flag.StringP("json", "j", "", "JSON text") flag.VarP(&pathStrings, "path", "p", "One or more paths to target in JSON") showKeysPtr := flag.BoolP("keys", "k", false, "Print keys & indexes that lead to value") flag.Usage = func() { fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0]) flag.PrintDefaults() fmt.Fprintln(os.Stderr, "Pipe JSON to StdIn by not specifying --file or --json ") } flag.Parse() if len(pathStrings) == 0 { fmt.Println("Must specify one or more paths with the --path flag") os.Exit(1) } paths, err := jsonpath.ParsePaths(pathStrings...) if err != nil { fmt.Println(fmt.Errorf("Failed to parse paths: %q", err.Error())) os.Exit(1) } if filePtr != nil && *filePtr != "" { f, err := os.Open(*filePtr) if err != nil { fmt.Println(fmt.Errorf("Failed to open file: %q", err.Error())) os.Exit(1) } eval, err := jsonpath.EvalPathsInReader(f, paths) checkAndHandleError(err) run(eval, *showKeysPtr) checkAndHandleError(eval.Error) f.Close() } else if jsonPtr != nil && *jsonPtr != "" { eval, err := jsonpath.EvalPathsInBytes([]byte(*jsonPtr), paths) checkAndHandleError(err) run(eval, *showKeysPtr) checkAndHandleError(eval.Error) } else { reader := bufio.NewReader(os.Stdin) eval, err := jsonpath.EvalPathsInReader(reader, paths) checkAndHandleError(err) run(eval, *showKeysPtr) checkAndHandleError(eval.Error) } }