1JO(1)                                                                    JO(1)
2
3
4

NAME

6       jo - JSON output from a shell
7

SYNOPSIS

9       jo  [-p]  [-a]  [-B] [-e] [-v] [-V] [-d keydelim] [–] [ [-s|-n|-b] word
10       ...]
11

DESCRIPTION

13       jo creates a JSON string on stdout from _word_s given it  as  arguments
14       or  read  from stdin.  Without option -a it generates an object whereby
15       each word is a key=value (or key@value) pair with key  being  the  JSON
16       object  element  and value its value.  jo attempts to guess the type of
17       value in order to create number (using strtod(3)), string, or null val‐
18       ues in JSON.
19
20       jo  normally treats key as a literal string value.  If the -d option is
21       specified, key will be interpreted as an object path, whose  individual
22       components are separated by the first character of keydelim.
23
24       jo  normally  treats  value as a literal string value, unless it begins
25       with one of the following characters:
26
27       value   action
28       ───────────────────────────────────
29       @file   substitute the contents of
30               file as-is
31       %file   substitute the contents of
32               file   in   base64-encoded
33               form
34       :file   interpret  the contents of
35               file as JSON, and  substi‐
36               tute the result
37
38       Escape the special character with a backslash to prevent this interpre‐
39       tation.
40
41       jo treats key@value specifically as boolean JSON elements: if the value
42       begins with T, t, or the numeric value is greater than zero, the result
43       is true, else false.  A missing or empty value behind the colon results
44       in a null JSON element.
45
46       jo creates an array instead of an object when -a is specified.
47
48       When  the := operator is used in a word, the name to the right of := is
49       a file containing JSON which is parsed and assigned to the key left  of
50       the  operator.   The file may be specified as - to read from jo’s stan‐
51       dard input.
52

TYPE COERCION

54       jo’s type guesses can be overridden on a per-word  basis  by  prefixing
55       word with -s for string, -n for number, or -b for boolean.  The list of
56       _word_s must be prefixed with --, to indicate to jo that there  are  no
57       more global options.
58
59       Type coercion works as follows:
60
61       word         -s             -n          -b          default
62       ─────────────────────────────────────────────────────────────────
63       a=           “a”:""         “a”:0       “a”:false   “a”:null
64       a=string     “a”:“string”   “a”:6       “a”:true    “a”:“string”
65
66
67       a="quoted"   “a”:“"quot‐    “a”:8       “a”:true    “a”:“"quot‐
68                    ed"”                                   ed"”
69       a=12345      “a”:“12345”    “a”:12345   “a”:true    “a”:12345
70       a=true       “a”:“true”     “a”:1       “a”:true    “a”:true
71       a=false      “a”:“false”    “a”:0       “a”:false   “a”:false
72       a=null       “a”:""         “a”:0       “a”:false   “a”:null
73
74       Coercing  a  non-number  string  to  number  outputs  the length of the
75       string.
76
77       Coercing a non-boolean string to boolean outputs false if the string is
78       empty, true otherwise.
79
80       Type  coercion only applies to key=value words, and individual words in
81       a -a array.  Coercing other words has no effect.
82

EXAMPLES

84       Create an object.  Note how the incorrectly-formatted float  value  be‐
85       comes a string:
86
87              $ jo tst=1457081292 lat=12.3456 cc=FR badfloat=3.14159.26 name="JP Mens" nada= coffee@T
88              {"tst":1457081292,"lat":12.3456,"cc":"FR","badfloat":"3.14159.26","name":"JP Mens","nada":null,"coffee":true}
89
90       Pretty-print an array with a list of files in the current directory:
91
92              $ jo -p -a *
93              [
94               "Makefile",
95               "README.md",
96               "jo.1",
97               "jo.c",
98               "jo.pandoc",
99               "json.c",
100               "json.h"
101              ]
102
103       Create  objects within objects; this works because if the first charac‐
104       ter of value is an open brace or a bracket we attempt to decode the re‐
105       mainder as JSON.  Beware spaces in strings ...
106
107              $ 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
108              {
109               "name": "JP",
110               "object": {
111                "fruit": "Orange",
112                "hungry": false,
113                "point": {
114                 "x": 10,
115                 "y": 20,
116                 "list": [
117                  1,
118                  2,
119                  3,
120                  4,
121                  5
122                 ]
123                },
124                "number": 17
125               },
126               "sunday": false
127              }
128
129       Booleans  as strings or as boolean (pay particular attention to switch;
130       the -B option disables the default detection of  the  “true”,  “false”,
131       and “null” strings):
132
133              $ jo switch=true morning@0
134              {"switch":true,"morning":false}
135
136              $ jo -B switch=true morning@0
137              {"switch":"true","morning":false}
138
139       Elements  (objects  and  arrays)  can be nested.  The following example
140       nests an array called point and an object named geo:
141
142              $ jo -p name=Jane point[]=1 point[]=2 geo[lat]=10 geo[lon]=20
143              {
144                 "name": "Jane",
145                 "point": [
146                    1,
147                    2
148                 ],
149                 "geo": {
150                    "lat": 10,
151                    "lon": 20
152                 }
153              }
154
155       The same example, using object paths:
156
157              $ jo -p -d. name=Jane point[]=1 point[]=2 geo.lat=10 geo.lon=20
158              {
159                 "name": "Jane",
160                 "point": [
161                    1,
162                    2
163                 ],
164                 "geo": {
165                    "lat": 10,
166                    "lon": 20
167                 }
168              }
169
170       Without -d, a different object is generated:
171
172              $ jo -p name=Jane point[]=1 point[]=2 geo.lat=10 geo.lon=20
173              {
174                 "name": "Jane",
175                 "point": [
176                    1,
177                    2
178                 ],
179                 "geo.lat": 10,
180                 "geo.lon": 20
181              }
182
183       Create empty objects or arrays, intentionally or potentially:
184
185              $ jo < /dev/null
186              {}
187
188              $ MY_ARRAY=(a=1 b=2)
189              $ jo -a "${MY_ARRAY[@]}" < /dev/null
190              ["a=1","b=2"]
191
192       Type coercion:
193
194              $ 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"
195              {
196                 "a": "true",
197                 "b": true,
198                 "c": "123",
199                 "d": 123,
200                 "e": true,
201                 "f": true,
202                 "g": 14,
203                 "h": true
204              }
205
206              $ jo -a -- -s 123 -n "This is a test" -b C_Rocks 456
207              ["123",14,true,456]
208
209       Read element values from files: a value which starts with @ is read  in
210       plain whereas if it begins with a % it will be base64-encoded and if it
211       starts with : the contents are interpreted as JSON:
212
213              $ jo program=jo authors=@AUTHORS
214              {"program":"jo","authors":"Jan-Piet Mens <jpmens@gmail.com>"}
215
216              $ jo filename=AUTHORS content=%AUTHORS
217              {"filename":"AUTHORS","content":"SmFuLVBpZXQgTWVucyA8anBtZW5zQGdtYWlsLmNvbT4K"}
218
219              $ jo nested=:nested.json
220              {"nested":{"field1":123,"field2":"abc"}}
221
222       These characters can be escaped to avoid interpretation:
223
224              $ jo name="JP Mens" twitter='\@jpmens'
225              {"name":"JP Mens","twitter":"@jpmens"}
226
227              $ jo char=" " URIescape=\\%20
228              {"char":" ","URIescape":"%20"}
229
230              $ jo action="split window" vimcmd="\:split"
231              {"action":"split window","vimcmd":":split"}
232
233       Read element values from a file in order  to  overcome  ARG_MAX  limits
234       during object assignment:
235
236              $ ls | jo -a > child.json
237              $ jo files:=child.json
238              {"files":["AUTHORS","COPYING","ChangeLog" ....
239
240              $ ls *.c | jo -a > source.json; ls *.h | jo -a > headers.json
241              $ jo -a :source.json :headers.json
242              [["base64.c","jo.c","json.c"],["base64.h","json.h"]]
243

OPTIONS

245       jo understands the following global options.
246
247       -a     Interpret the list of words as array values and produce an array
248              instead of an object.
249
250       -B     By default jo interprets the strings “true” and “false” as bool‐
251              ean  elements  true  and false respectively, and “null” as null.
252              Disable with this option.
253
254       -e     Ignore empty stdin (i.e. don’t produce a diagnostic  error  when
255              stdin is empty)
256
257       -p     Pretty-print  the  JSON  string  on  output instead of the terse
258              one-line output it prints by default.
259
260       -v     Show version and exit.
261
262       -V     Show version as a JSON object and exit.
263

BUGS

265       Probably.
266
267       If a value given to jo expands to empty in the shell, then jo  produces
268       a  null  in  object mode, and might appear to hang in array mode; it is
269       not hanging, rather it’s reading stdin.  This is not a bug.
270
271       Numeric values are converted to numbers which can produce undesired re‐
272       sults.   If  you quote a numeric value, jo will make it a string.  Com‐
273       pare the following:
274
275              $ jo a=1.0
276              {"a":1}
277              $ jo a=\"1.0\"
278              {"a":"1.0"}
279
280       Omitting a closing bracket on a nested element causes a diagnostic mes‐
281       sage  to  print,  but the output contains garbage anyway.  This was de‐
282       signed thusly.
283

RETURN CODES

285       jo exits with a code 0 on success and non-zero on failure  after  indi‐
286       cating what caused the failure.
287

AVAILABILITY

289       <http://github.com/jpmens/jo>
290

CREDITS

292       · This program uses json.[ch], by Joseph A.  Adams.
293

SEE ALSO

295       · <https://stedolan.github.io/jq/>
296
297       · <https://github.com/micha/jsawk>
298
299       · <https://github.com/jtopjian/jsed>
300
301       · strtod(3)
302

AUTHOR

304       Jan-Piet Mens <http://jpmens.net>
305
306
307
308User Manuals                                                             JO(1)
Impressum