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

NAME

6       jo - JSON output from a shell
7

SYNOPSIS

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

DESCRIPTION

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

TYPE COERCION

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

EXAMPLES

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

OPTIONS

265       jo understands the following global options.
266
267       -a     Interpret the list of words as array values and produce an array
268              instead of an object.
269
270       -B     By  default,  jo  interprets  the  strings “true” and “false” as
271              boolean elements true and  false  respectively,  and  “null”  as
272              null.  Disable with this option.
273
274       -D     Deduplicate object keys.
275
276       -e     Ignore  empty  stdin (i.e. don’t produce a diagnostic error when
277              stdin is empty)
278
279       -n     Do not add keys with empty values.
280
281       -p     Pretty-print the JSON string on output instead of the terse one-
282              line output it prints by default.
283
284       -v     Show version and exit.
285
286       -V     Show version as a JSON object and exit.
287

BUGS

289       Probably.
290
291       If  a value given to jo expands to empty in the shell, then jo produces
292       a null in object mode, and might appear to hang in array  mode;  it  is
293       not hanging, rather it’s reading stdin.  This is not a bug.
294
295       Numeric values are converted to numbers which can produce undesired re‐
296       sults.  If you quote a numeric value, jo will make it a  string.   Com‐
297       pare the following:
298
299              $ jo a=1.0
300              {"a":1}
301              $ jo a=\"1.0\"
302              {"a":"1.0"}
303
304       Omitting a closing bracket on a nested element causes a diagnostic mes‐
305       sage to print, but the output contains garbage anyway.   This  was  de‐
306       signed thusly.
307

RETURN CODES

309       jo  exits  with a code 0 on success and non-zero on failure after indi‐
310       cating what caused the failure.
311

AVAILABILITY

313       <http://github.com/jpmens/jo>
314

CREDITS

316       • This program uses json.[ch], by Joseph A.  Adams.
317

SEE ALSO

319       • <https://stedolan.github.io/jq/>
320
321       • <https://github.com/micha/jsawk>
322
323       • <https://github.com/jtopjian/jsed>
324
325strtod(3)
326

AUTHOR

328       Jan-Piet Mens <http://jpmens.net>
329
330
331
332User Manuals                                                             JO(1)
Impressum