Challenge Easy

Call an HTTP API with curl: Processing JSON Responses with jq

Practice one of the most common command-line combinations for HTTP API access: fetch a JSON response with curl and pipe it into jq to pretty print, reshape, or get only the relevant parts.

Premium Challenge

Upgrade your membership to unlock this and all other premium materials.

Upgrade

HTTP APIs usually respond with JSON, and jq is the command-line tool for reading JSON. Piping curl into jq lets you pull one field out of a response, list an array, filter it, or compute something from it, in a one-off command or in a script.

In this challenge, you will practice such curl and jq pipelines on workstation-01 against the internal Artifact Inventory API at http://api.corp.internal:8080. The endpoints you need:

  • GET /api/v1/status - get service health, version, and build information
  • GET /api/v1/artifacts - list all artifacts known to the service
  • GET /api/v1/artifacts/<name>/manifest - read the manifest of an artifact

Task 1: Pull Out a Nested Field

The status endpoint reports which commit the service was built from, inside its build object. Which commit is it?

Hint 1

The jq command reads JSON from stdin when no file is given, so the output of curl can be piped into it. The filter . prints the whole document nicely formatted, which is a good first step for any endpoint:

curl -s http://api.corp.internal:8080/api/v1/status | jq .

The -s option keeps the progress meter of curl out of the output.

Hint 2

The filter .foo prints the value of the foo key, and keys of nested objects are chained with dots. The -r option prints the value as a raw string, without the JSON quotes:

echo '{"foo":{"bar":"hello"}}' | jq -r '.foo.bar'
hello

Task 2: List an Array One Element per Line

Write the names of all artifacts known to the service to ~/artifacts.txt, one bare name per line, without quotes, commas, or brackets.

Hint 3

The [] suffix iterates over an array, so .foo[] prints each element of foo as a separate output, and .foo[].bar prints one field of each. Without -r, the strings come out with quotes around them:

echo '{"foo":[{"bar":"apple"},{"bar":"banana"}]}' | jq -r '.foo[].bar'
apple
banana

Task 3: Filter Objects by an Attribute

Some artifacts are built for linux/arm64 and some for linux/amd64. Write the names of the linux/arm64 artifacts to ~/arm64.txt, one per line.

Hint 4

The select(<condition>) function keeps only the inputs for which the condition is true. String comparison uses ==, and a | .bar at the end picks the field to print:

echo '{"foo":[{"bar":"apple","color":"red"},{"bar":"banana","color":"yellow"}]}' | jq -r '.foo[] | select(.color == "yellow") | .bar'
banana

Task 4: Compute a Value

How many bytes do all artifacts take together? Add up the sizeBytes field of every artifact.

Hint 5

Square brackets around a filter collect its outputs into an array, and the add function sums an array of numbers:

echo '{"foo":[{"bar":10},{"bar":20},{"bar":5}]}' | jq '[.foo[].bar] | add'
35

Task 5: Collect Several Values at Once

The manifest of report-builder references one config object and several layers, each by digest. Write the config digest and every layer digest to ~/digests.txt, one per line. Remember that the manifest endpoint returns JSON only when asked for it with the Accept: application/vnd.corp.manifest.v2+json header.

Hint 6

A comma separates several filters, and jq prints the results of all of them in order. The comma works with iteration as well:

echo '{"foo":{"bar":"apple"},"baz":[{"bar":"banana"},{"bar":"cherry"}]}' | jq -r '.foo.bar, .baz[].bar'
apple
banana
cherry