Skip to content
Latchkey

jo: Build JSON From the Shell

jo builds a JSON object from key=value arguments, handling types and nesting so you do not hand-assemble JSON with echo and risk broken quoting.

Constructing JSON payloads in bash with string concatenation is a quoting minefield. jo takes key=value pairs and emits valid JSON, escaping values for you.

What it does

jo turns its key=value arguments into a JSON object. It infers numbers and booleans, builds arrays with -a, nests via key=$(jo ...) substitution or the key[subkey]= syntax, and forces a string with a : prefix on the value.

Common usage

Terminal
# simple object with inferred types
jo name=ada age=42 active=true
# array of values
jo -a 1 2 3
# nested object via substitution
jo user=$(jo name=ada id=1) ts=$(date +%s)
# force a value to stay a string
jo zip=:01234

Options

Form / flagWhat it does
key=valueAdd a key with an inferred type
-aProduce a JSON array from the arguments
key=:valueForce the value to be a string
key=@fileRead the value from a file
key=%fileBase64-encode a file as the value
-pPretty-print the output

In CI

Build a webhook or API payload safely: jo event=deploy sha="$GITHUB_SHA" ok=true | curl -d @- "$WEBHOOK". Because jo escapes values, a commit message with quotes or newlines will not corrupt the JSON the way a hand-built echo "{...}" would.

Common errors in CI

jo: command not found: apt-get install jo or brew install jo. A value like 007 or true is coerced to a number/boolean unexpectedly; prefix with : to keep it a string (code=:007). An argument missing the = triggers jo: argument ... is neither k=v nor k@v. Unquoted values containing spaces get split by the shell into separate arguments, so quote them: msg="hello world".

Related guides

Run this faster and cheaper on Latchkey managed runners. Start free →