diff --git a/cmd/api.go b/cmd/api.go index fe0fd85..e336c8f 100644 --- a/cmd/api.go +++ b/cmd/api.go @@ -35,7 +35,17 @@ If --field is used and no --method is specified, the method defaults to POST.`, fj api /users/johndoe # Use raw body from stdin - echo '{"title":"test"}' | fj api /repos/{owner}/{repo}/issues --input -`, + echo '{"title":"test"}' | fj api /repos/{owner}/{repo}/issues --input - + + # Filter the response with a jq expression + fj api /repos/{owner}/{repo}/issues --jq '.[].title' + + # Project the response down to specific fields (requires "=" because --json + # also accepts an empty value to mean "all fields as JSON") + fj api /repos/{owner}/{repo} --json=full_name,description,private + + # Same projection without the "=" quirk + fj api /repos/{owner}/{repo} --json-fields full_name,description,private`, Args: cobra.ExactArgs(1), RunE: runAPI, } @@ -50,6 +60,7 @@ func init() { apiCmd.Flags().StringArrayP("header", "H", nil, "Add an HTTP request header (key:value)") apiCmd.Flags().Bool("silent", false, "Do not print the response body") apiCmd.Flags().BoolP("include", "i", false, "Include HTTP response headers in the output") + addJSONFlags(apiCmd, "Output the response as JSON; pass a comma-separated field list to project specific keys") } func runAPI(cmd *cobra.Command, args []string) error { @@ -212,18 +223,31 @@ func runAPI(cmd *cobra.Command, args []string) error { return nil } - // Pretty-print JSON, or output raw if not JSON contentType := resp.Header.Get("Content-Type") - if strings.Contains(contentType, "json") || json.Valid(respBody) { + isJSON := strings.Contains(contentType, "json") || json.Valid(respBody) + + // If the user asked for JSON projection or jq filtering, route through + // the shared JSON output helpers so the API command is consistent with + // `fj repo list`, `fj pr list`, etc. + if wantJSON(cmd) { + if !isJSON { + return fmt.Errorf("--json/--json-fields/--jq requires a JSON response, but the server returned %s", contentType) + } + var parsed any + if err := json.Unmarshal(respBody, &parsed); err != nil { + return fmt.Errorf("response is not valid JSON: %w", err) + } + return outputJSON(cmd, parsed) + } + + // Pretty-print JSON by default, otherwise emit raw bytes. + if isJSON { var parsed any if err := json.Unmarshal(respBody, &parsed); err == nil { - enc := json.NewEncoder(ios.Out) - enc.SetIndent("", " ") - return enc.Encode(parsed) + return writeJSON(parsed) } } - // Raw output for non-JSON responses _, err = ios.Out.Write(respBody) return err }