$ jb Hello=world array:number[]@<(seq 10) object:json@<(date=$(date -Iseconds) jb @date)
{"Hello":"world","array":[1,2,3,4,5,6,7,8,9,10],"object":{"date":"2024-07-03T19:26:36+00:00"}}
Alternatively, using the :{} object entry syntax: jb Hello=world array:number[]@<(seq 10) object:{}=date=$(date -Iseconds)
{"Hello":"world","array":[1,2,3,4,5,6,7,8,9,10],"object":{"date":"2024-07-03T19:30:26+00:00"}} $ jb size:number=oops; echo $?
json.encode_number(): not all inputs are numbers: 'oops'
json(): Could not encode the value of argument 'size:number=oops' as a 'number' value. Read from inline value.
␘
1
If you pipe the jb error into jq, jq fails to parse the JSON (because of the Cancel ctrl char) and also errors: $ jb size:number=oops | jq
json.encode_number(): not all inputs are numbers: 'oops'
json(): Could not encode the value of argument 'size:number=oops' as a 'number' value. Read from inline value.
parse error: Invalid numeric literal at line 2, column 0
$ declare -p PIPESTATUS
declare -a PIPESTATUS=([0]="1" [1]="4")
So jq exits with status 4 here. $ jb ===msg==:==hi=
{"=msg=":"=hi="}
In the key part, the first = begins the key, the == following are an escaped =. The first = following the : marks the value, and everything after is not parsed, so =hi= is literal. $ k='=msg=' v='=hi=' jb @k@v
{"=msg=":"=hi="} $ source json.bash
$ declare -A greeting=([Hello]=World)
$ json ...@greeting:{}
{"Hello":"World"}
... is splatting the greeting associative array entries into the object created by the json call. $ declare -A greeting=([Hello]=World [How]="are you?")
$ json @greeting:{}
{"greeting":{"Hello":"World","How":"are you?"}}
Vs: $ json ...@greeting:{}
{"Hello":"World","How":"are you?"} $ jb dependencies:json='["Bash","Grep"]'
{"dependencies":["Bash","Grep"]}
$ jb foo=bar bar:json='"this is a well formed string"'
{"foo":"bar","bar":"this is a well formed string"}
And then you can indeed use command substitution to nest calls: $ jb foo:json=$(jb bar=baz)
{"foo":{"bar":"baz"}}
It works even better to use process substitution, this way the shell gives jb a
file path to a file to read, and so you don't need to quote the $() to avoid whitespace breaking things: $ jb foo:json@<(jb msg=$'no need\nto quote this!')
{"foo":{"msg":"no need\nto quote this!"}}
Another option is to use jb-array to generate arrays. (jb-array is best for tuple-like arrays with varying types): $ jb dependencies:json@<(jb-array Bash Grep)
{"dependencies":["Bash","Grep"]}
And if you use it from bash as a function, you can put values into a bash array and reference it: $ source json.bash
$ dependencies=(Bash Grep)
$ json @dependencies:[]
{"dependencies":["Bash","Grep"]} jo -- -s id=42 -n size=42 -s surname=null data=null
{"id":"42","size":42,"surname":"","data":null}
Notice that surname comes out as the empty string though, I think this must be a bug in jo!