1JO(1) JO(1)
2
3
4
6 jo - JSON output from a shell
7
9 jo [-p] [-a] [-B] [-e] [-v] [-V] [-d keydelim] [–] [ [-s|-n|-b] word
10 ...]
11
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
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
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
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
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
285 jo exits with a code 0 on success and non-zero on failure after indi‐
286 cating what caused the failure.
287
289 <http://github.com/jpmens/jo>
290
292 · This program uses json.[ch], by Joseph A. Adams.
293
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
304 Jan-Piet Mens <http://jpmens.net>
305
306
307
308User Manuals JO(1)