Json.bash
Command-line tool and bash library that creates JSON
Install / Use
/learn @h4l/Json.bashREADME
$ jb name=json.bash creates=JSON
json.bash is a command-line tool and bash library that creates JSON.
$ jb name=json.bash creates=JSON dependencies:[,]=Bash,Grep
{"name":"json.bash","creates":"JSON","dependencies":["Bash","Grep"]}
$ # Values are strings unless explicitly typed
$ jb id=42 size:number=42 surname=null data:null
{"id":"42","size":42,"surname":"null","data":null}
$ # Reference variables with @name
$ id=42 date=2023-06-23 jb @id created@date modified@date
{"id":"42","created":"2023-06-23","modified":"2023-06-23"}
$ # Pull data from files
$ printf hunter2 > /tmp/password; jb @/tmp/password
{"password":"hunter2"}
$ # Pull data from shell pipelines
$ jb sizes:number[]@<(seq 1 4)
{"sizes":[1,2,3,4]}
$ # Nest jb calls
$ jb type=club members:json[]@<(jb name=Bob; jb name=Alice)
{"type":"club","members":[{"name":"Bob"},{"name":"Alice"}]}
$ # The Bash API can reference arrays and create JSON efficiently — without forking
$ source json.bash
$ out=people json name=Bob; out=people json name=Alice; sizes=(42 91 2)
$ id="abc.123" json @id @sizes:number[] @people:json[]
{"id":"abc.123","sizes":[42,91,2],"people":[{"name":"Bob"},{"name":"Alice"}]}
json.bash's one thing is to get shell-native data (environment variables,
files, program output) to somewhere else, using JSON encapsulate it robustly.
Creating JSON from the command line or a shell script can be useful when:
- You need some ad-hoc JSON to interact with a JSON-consuming application
- You need to bundle up some data to share or move elsewhere. JSON can a good alternative to base64-encoding or a file archive.
It does no transformation or filtering itself, instead it pulls data from things you already know how to use, like files, command-line arguments, environment variables, shell pipelines and shell scripts. It glues together data from these sources, giving it enough structure to make the data easy to consume reliably in downstream programs.
It's something like a reverse tee — it pulls together data sources, using JSON
to represent the aggregation. It's not an alternative to to data-processing
tools like jq, rather it helps assemble JSON to send into JSON-consuming tools
like jq.
Contents
Install
Container image
We publish the container image
ghcr.io/h4l/json.bash/jb
with jb-* and json.bash, perhaps useful to try without installing.
$ docker container run --rm ghcr.io/h4l/json.bash/jb msg=Hi
{"msg":"Hi"}
$ # Get a bash shell to try things interactively
$ docker container run --rm -it ghcr.io/h4l/json.bash/jb
bash-5.2# jb os-release:{}@<(xargs < /etc/os-release env -i)
{"os-release":{"NAME":"Alpine Linux","ID":"alpine","VERSION_ID":"3.18.2","PRETTY_NAME":"Alpine Linux v3.18","HOME_URL":"https://alpinelinux.org/","BUG_REPORT_URL":"https://gitlab.alpinelinux.org/alpine/aports/-/issues"}}
OS Packages
<details> <summary>Expand this for details…</summary>Auto-generated packages
Externally-maintained packages are not yet
widely available, so we provide a way to generate a package file for any package
manager supported by fpm (at least apk, deb, freebsd, rpm, sh (self
extracting), tar, possibly more).
We publish the container image
ghcr.io/h4l/json.bash/pkg
that can generate a package file in whichever format you like:
$ docker container run --rm -v "$(pwd):/pkg" ghcr.io/h4l/json.bash/pkg deb
Generating: /pkg/json.bash_0.2.2-dev.deb
$ ls
json.bash_0.2.2-dev.deb
$ dpkg -i /pkg/json.bash_0.2.2-dev.deb
Externally-maintained packages
These packages have been created and maintained by downstream users/projects.
| OS | Repository | Details | | ---------- | ------------------------------------------------------------------------ | ------------------------------------------------ | | Arch linux | User Repository | https://aur.archlinux.org/packages/json-bash-git |
</details>json.bash needs you!
If you'd like
json.bashto be available from your operating system's package manager, you can help by investigating your package manager's process for adding new packages to see if you can contribute a package, or make a request to add it.
Manual install
Installing manually is quite straightforward.
<details> <summary>Expand this for instructions…</summary># Alternatively, use /usr/local/bin to install system-wide
cd ~/.local/bin
curl -fsSL -O "https://raw.githubusercontent.com/h4l/json.bash/HEAD/json.bash"
chmod +x json.bash
ln -s json.bash jb
ln -s json.bash jb-array
# If your shell is bash, you can alias jb and jb-array to the bash functions for
# better performance. You should add this line to your ~/.bashrc
source json.bash; alias jb=json jb-array=json.array
# Optional: if you'd also like jb-echo, jb-cat, jb-stream
for name in jb-echo jb-cat jb-stream; do
curl -fsSL -O "https://raw.githubusercontent.com/h4l/json.bash/HEAD/bin/${name:?}"
chmod +x "${name:?}"
done
To uninstall, remove json.bash, jb, jb-array, jb-echo, jb-cat and
jb-stream from the directory you installed them to (run which -a json.bash
to find where it is).
How-to guides
- The
json.bashcommands - Object keys
- Object values
- Arrays (mixed types, fixed length)
- Argument types
- Array values (uniform types, variable length)
- Object values (uniform types, variable length)
...arguments (merge entries into the host object/array)- Missing / empty values
- Nested JSON with
:jsonand:rawtypes - File references
- Argument structure
- Error handling
- Security and correctness
jb-cat,jb-echo,jb-streamutility programs- Streaming output
- Configuring environment variables
These examples mostly use jb, which is the json.bash library run as a
stand-alone program. From within a bash script you get better performance by
running source json.bash and using the json bash function, which is a
superset of stand-alone jb and much faster because it doesn't execute new
child processes when called. See the
Background & performance notes section for
more.
The json.bash commands
jb / jb-array / json / json.array
$ # The jb program creates JSON objects
$ jb
{}
$ # The jb-array creates arrays, but otherwise works like jb.
$ jb-array :number=4
[4]
$ # From a bash shell or bash script, use the json and json.array functions
$ source json.bash # no path is needed if json.bash is on $PATH
$ json
{}
$ # json.array creates arrays, but otherwise works like json
$ json.array
[]
Each argument defines an entry in the object or array. Arguments can contain a key, type and value in this structure:
<img width="100%" src="docs/syntax-diagrams/minimal-argument.svg" alt="A railroad syntax diagram showing a high-level summary of the key, type and value structure of an argument." title="Minimal Argument Structure Diagram">
The Argument structure section has more details.
Object keys
Each argument creates an entry in the JSON object. The first part of each argument defines the key.
$ jb msg=hi
{"msg":"hi"}
$ # Keys can contain most characters (except @:=, unless escaped)
$ jb "🐚"=JSON
{"🐚":"JSON"}
$ # Key values can come from variables
$ key="The Message" jb @key=hi
{"The Message":"hi"}
$ # Key variables can contain any characters
$ key="@key:with=reserved-chars" jb @key=hi
{"@key:with=reserved-chars":"hi"}
$ # Each argument defines a key
$ var=c jb a=X b=Y @var=Z
{"a":"X","b":"Y","c":"Z"}
$ # Keys may be reused, but should not be, because JSON parser behaviour for
$ # duplicate keys is undefined.
$ jb a=A a=B a=C
{"a":"A","a":"B","a":"C"}
$ # The reserved characters can be escaped by doubling them
$ jb =@@handle=ok a::z=ok 1+1==2=ok
{"@handle":"ok","a:z":"ok","1+1=2":"ok"}
Object values
The last part of each argument after a = or @ defines the value. Values can
contain their value directly, or reference a variable or file.
$ jb message="Hello World"
{"message":"Hello World"}
$ greeting="Hi there" jb message@greeting
{"message":"Hi there"}
$ # Variable references without a value define the key and value in one go.
$ greeting="Hi" name=Bob jb @greeting @name
{"greeting":"Hi","name":"Bob"}
$ # This also applies (less usefully) to inline entries.
$ jb message
{"message":"message"}
$ # Inline values following a `=` have no content restrictions.
$ jb message=@value:with=reserved-chars
{"message":"@value:with=reserved-chars"}
$ # @ values that begin with / or ./ are references to files
$ printf hunter2 > /tmp/password; jb secret@/tmp/password
{"secret":"hunter2"}
$ # File references without a value define the key and value in one go.
$ jb
Related Skills
node-connect
340.2kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
84.1kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
340.2kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
commit-push-pr
84.1kCommit, push, and open a PR
