Skip to content
Latchkey

jo: Build JSON From the Shell

jo turns key=value arguments into a JSON object, inferring numbers and booleans, so you can build a request body or payload without hand-writing brackets and quotes.

jo is jq run backwards: instead of querying JSON it produces it. For webhook payloads and API bodies in shell scripts, it beats fragile printf-with-escapes.

What it does

jo reads key=value pairs and emits a JSON object. It auto-types bare numbers and true/false/null; key=@file reads a value from a file; -a makes a top-level array; nesting is done by piping a jo array/object into a key=$(...) with -d for dotted keys. := is not jo syntax; use = and let inference or -s/-n control typing.

Common usage

bash
jo name=Ada active=true age=36
# -> {"name":"Ada","active":true,"age":36}
jo -a 1 2 3                         # -> [1,2,3]
jo user=$(jo name=Ada id=7) ok=true    # nested object
jo -p msg="hello world" count=5    # -p pretty-prints
http POST api/users $(jo name=Ada role=admin)   # build a body

Options

Flag / formWhat it does
key=valueAdd a field; numbers/bools/null are auto-typed
-aProduce a JSON array from the bare values
-pPretty-print with indentation
key=@fileUse the file contents as the value
key=%fileBase64-encode the file as the value
-sForce every value to be a string (disable type inference)
-nDrop keys whose value is an empty string

In CI

jo guarantees valid JSON and proper escaping, which is exactly what hand-built strings get wrong when a value contains a quote or space. Quote the whole value when it has spaces (msg="hello world"). Use -s when a value that looks numeric (a zip code, a version) must stay a string.

Common errors in CI

"jo: command not found" (install via apt-get install -y jo, brew install jo, or build from source). A value with spaces splitting into multiple args means it was unquoted; wrap it in quotes. A leading-zero or version string becoming a number (or an error) means type inference kicked in; force a string with -s or by quoting per the jo docs. Nested objects need a sub-jo, not literal braces.

Related guides

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