1% JO(1) User Manuals 2 3# NAME 4 5jo - JSON output from a shell 6 7# SYNOPSIS 8 9jo [-p] [-a] [-B] [-e] [-v] [-V] [-d keydelim] [--] [ [-s|-n|-b] word ...] 10 11# DESCRIPTION 12 13*jo* creates a JSON string on _stdout_ from _word_s given it as arguments or read from _stdin_. Without 14option `-a` it generates an object whereby each _word_ is a `key=value` (or `key@value`) 15pair with _key_ being the JSON object element and _value_ its value. *jo* attempts to 16guess the type of _value_ in order to create number (using _strtod(3)_), string, or null values in JSON. 17 18*jo* normally treats _key_ as a literal string value. If the `-d` option is specified, _key_ will be 19interpreted as an _object path_, whose individual components are separated by the first character of _keydelim_. 20 21*jo* normally treats _value_ as a literal string value, unless it begins with one of the following characters: 22 23value action 24----- ------ 25@file substitute the contents of _file_ as-is 26%file substitute the contents of _file_ in base64-encoded form 27:file interpret the contents of _file_ as JSON, and substitute the result 28 29Escape the special character with a backslash to prevent this interpretation. 30 31*jo* treats `key@value` specifically as boolean JSON elements: if the value begins with `T`, `t`, 32or the numeric value is greater than zero, the result is `true`, else `false`. A missing or 33empty value behind the colon results in a `null` JSON element. 34 35*jo* creates an array instead of an object when `-a` is specified. 36 37When the `:=` operator is used in a _word_, the name to the right of `:=` is a file containing JSON which is parsed and assigned to the key left of the operator. The file may be specified as `-` to read from _jo_'s standard input. 38 39 40# TYPE COERCION 41 42*jo*'s type guesses can be overridden on a per-word basis by prefixing _word_ with `-s` for _string_, 43`-n` for _number_, or `-b` for _boolean_. The list of _word_s *must* be prefixed with `--`, to indicate 44to *jo* that there are no more global options. 45 46Type coercion works as follows: 47 48word -s -n -b default 49------------ ---------------- ------------ --------- ---------------- 50a= "a":"" "a":0 "a":false "a":null 51a=string "a":"string" "a":6 "a":true "a":"string" 52a=\"quoted\" "a":"\"quoted\"" "a":8 "a":true "a":"\"quoted\"" 53a=12345 "a":"12345" "a":12345 "a":true "a":12345 54a=true "a":"true" "a":1 "a":true "a":true 55a=false "a":"false" "a":0 "a":false "a":false 56a=null "a":"" "a":0 "a":false "a":null 57 58Coercing a non-number string to number outputs the _length_ of the string. 59 60Coercing a non-boolean string to boolean outputs `false` if the string is empty, `true` otherwise. 61 62Type coercion only applies to `key=value` words, and individual words in a `-a` array. 63Coercing other words has no effect. 64 65# EXAMPLES 66 67Create an object. Note how the incorrectly-formatted float value becomes a string: 68 69 $ jo tst=1457081292 lat=12.3456 cc=FR badfloat=3.14159.26 name="JP Mens" nada= coffee@T 70 {"tst":1457081292,"lat":12.3456,"cc":"FR","badfloat":"3.14159.26","name":"JP Mens","nada":null,"coffee":true} 71 72Pretty-print an array with a list of files in the current directory: 73 74 $ jo -p -a * 75 [ 76 "Makefile", 77 "README.md", 78 "jo.1", 79 "jo.c", 80 "jo.pandoc", 81 "json.c", 82 "json.h" 83 ] 84 85Create objects within objects; this works because if the first character of value is an open brace or a bracket we attempt to decode the remainder as JSON. Beware spaces in strings ... 86 87 $ jo -p name=JP object=$(jo fruit=Orange hungry@0 point=$(jo x=10 y=20 list=$(jo -a 1 2 3 4 5)) number=17) sunday@0 88 { 89 "name": "JP", 90 "object": { 91 "fruit": "Orange", 92 "hungry": false, 93 "point": { 94 "x": 10, 95 "y": 20, 96 "list": [ 97 1, 98 2, 99 3, 100 4, 101 5 102 ] 103 }, 104 "number": 17 105 }, 106 "sunday": false 107 } 108 109Booleans as strings or as boolean (pay particular attention to _switch_; the `-B` option disables the default detection of the "`true`", "`false`", and "`null`" strings): 110 111 $ jo switch=true morning@0 112 {"switch":true,"morning":false} 113 114 $ jo -B switch=true morning@0 115 {"switch":"true","morning":false} 116 117Elements (objects and arrays) can be nested. The following example nests an array called _point_ and an object named _geo_: 118 119 $ jo -p name=Jane point[]=1 point[]=2 geo[lat]=10 geo[lon]=20 120 { 121 "name": "Jane", 122 "point": [ 123 1, 124 2 125 ], 126 "geo": { 127 "lat": 10, 128 "lon": 20 129 } 130 } 131 132The same example, using object paths: 133 134 $ jo -p -d. name=Jane point[]=1 point[]=2 geo.lat=10 geo.lon=20 135 { 136 "name": "Jane", 137 "point": [ 138 1, 139 2 140 ], 141 "geo": { 142 "lat": 10, 143 "lon": 20 144 } 145 } 146 147Without `-d`, a different object is generated: 148 149 $ jo -p name=Jane point[]=1 point[]=2 geo.lat=10 geo.lon=20 150 { 151 "name": "Jane", 152 "point": [ 153 1, 154 2 155 ], 156 "geo.lat": 10, 157 "geo.lon": 20 158 } 159 160Create empty objects or arrays, intentionally or potentially: 161 162 $ jo < /dev/null 163 {} 164 165 $ MY_ARRAY=(a=1 b=2) 166 $ jo -a "${MY_ARRAY[@]}" < /dev/null 167 ["a=1","b=2"] 168 169 170Type coercion: 171 172 $ jo -p -- -s a=true b=true -s c=123 d=123 -b e="1" -b f="true" -n g="This is a test" -b h="This is a test" 173 { 174 "a": "true", 175 "b": true, 176 "c": "123", 177 "d": 123, 178 "e": true, 179 "f": true, 180 "g": 14, 181 "h": true 182 } 183 184 $ jo -a -- -s 123 -n "This is a test" -b C_Rocks 456 185 ["123",14,true,456] 186 187Read element values from files: a value which starts with `@` is read in plain whereas if it begins with a `%` it will be base64-encoded and if it starts with `:` the contents are interpreted as JSON: 188 189 $ jo program=jo authors=@AUTHORS 190 {"program":"jo","authors":"Jan-Piet Mens <jpmens@gmail.com>"} 191 192 $ jo filename=AUTHORS content=%AUTHORS 193 {"filename":"AUTHORS","content":"SmFuLVBpZXQgTWVucyA8anBtZW5zQGdtYWlsLmNvbT4K"} 194 195 $ jo nested=:nested.json 196 {"nested":{"field1":123,"field2":"abc"}} 197 198These characters can be escaped to avoid interpretation: 199 200 $ jo name="JP Mens" twitter='\@jpmens' 201 {"name":"JP Mens","twitter":"@jpmens"} 202 203 $ jo char=" " URIescape=\\%20 204 {"char":" ","URIescape":"%20"} 205 206 $ jo action="split window" vimcmd="\:split" 207 {"action":"split window","vimcmd":":split"} 208 209Read element values from a file in order to overcome ARG_MAX limits during object assignment: 210 211 $ ls | jo -a > child.json 212 $ jo files:=child.json 213 {"files":["AUTHORS","COPYING","ChangeLog" .... 214 215 $ ls *.c | jo -a > source.json; ls *.h | jo -a > headers.json 216 $ jo -a :source.json :headers.json 217 [["base64.c","jo.c","json.c"],["base64.h","json.h"]] 218 219# OPTIONS 220 221*jo* understands the following global options. 222 223-a 224: Interpret the list of _words_ as array values and produce an array instead of 225 an object. 226 227-B 228: By default *jo* interprets the strings "`true`" and "`false`" as boolean elements 229 `true` and `false` respectively, and "`null`" as `null`. Disable with this option. 230 231-e 232: Ignore empty stdin (i.e. don't produce a diagnostic error when *stdin* 233 is empty) 234 235-p 236: Pretty-print the JSON string on output instead of the terse one-line output it 237 prints by default. 238 239-v 240: Show version and exit. 241 242-V 243: Show version as a JSON object and exit. 244 245# BUGS 246 247Probably. 248 249If a value given to *jo* expands to empty in the shell, then *jo* produces a `null` in object mode, and might appear to hang in array mode; it is not hanging, rather it's reading _stdin_. This is not a bug. 250 251Numeric values are converted to numbers which can produce undesired results. If you quote a numeric value, *jo* will make it a string. Compare the following: 252 253 $ jo a=1.0 254 {"a":1} 255 $ jo a=\"1.0\" 256 {"a":"1.0"} 257 258Omitting a closing bracket on a nested element causes a diagnostic message to print, but the output contains garbage anyway. This was designed thusly. 259 260# RETURN CODES 261 262*jo* exits with a code 0 on success and non-zero on failure after indicating what 263caused the failure. 264 265# AVAILABILITY 266 267<http://github.com/jpmens/jo> 268 269# CREDITS 270 271* This program uses `json.[ch]`, by Joseph A. Adams. 272 273# SEE ALSO 274 275* <https://stedolan.github.io/jq/> 276* <https://github.com/micha/jsawk> 277* <https://github.com/jtopjian/jsed> 278* strtod(3) 279 280# AUTHOR 281 282Jan-Piet Mens <http://jpmens.net> 283 284