curl piped to jq: Parse API JSON in CI
curl -s url | jq -e '.field' fetches an API response and extracts or asserts a field, failing the step when jq's filter yields false or null.
The curl-into-jq pattern is the workhorse of shell-based API checks: curl fetches the JSON, jq queries it, and jq -e turns the queried value into an exit code you can gate on.
What it does
curl fetches the response body and jq parses and queries it. With -e (--exit-status), jq exits 1 if the last output is false or null and 0 otherwise, so a query like .status == "ok" becomes a pass/fail gate. -r prints raw strings without JSON quotes for use in later shell steps.
Common usage
# extract a field into a shell variable
id=$(curl -s example.com/api/me | jq -r '.id')
# gate: fail the step unless status is "ok"
curl -s example.com/health | jq -e '.status == "ok"' > /dev/null
# assert an array is non-empty
curl -s example.com/api/items | jq -e '.items | length > 0' > /dev/nullOptions
| Piece | What it does |
|---|---|
| curl -s | Silent: no progress meter to pollute the pipe |
| curl -f | Fail (exit 22) on HTTP 4xx/5xx before jq runs |
| jq -e | Exit 1 when the result is false or null |
| jq -r | Raw output: strings without surrounding quotes |
| jq -c | Compact single-line output |
In CI
Add curl -f so an HTTP error fails before jq ever parses an error page, and remember set -o pipefail in bash so a curl failure on the left of the pipe is not masked by a passing jq on the right. Use jq -e whenever the query is meant to be an assertion.
Common errors in CI
jq: error (at <stdin>:0): Cannot index string with "field" or parse error: Invalid numeric literal means jq received HTML or an error page instead of JSON; add curl -f to fail early. jq: error: null (null) has no keys means the path did not exist. A silent pass on a failed request means pipefail is off, so bash only saw jq's exit code.