1 | ---
|
2 | default_highlighter: oils-sh
|
3 | ---
|
4 |
|
5 | JSON in Oils
|
6 | ===========
|
7 |
|
8 | [JSON](https://www.json.org/) is used by both web services and command line
|
9 | tools, so a modern Unix shell needs to support it.
|
10 |
|
11 | Oils has a `json` builtin which you can use from bot OSH and YSH.
|
12 |
|
13 | It also has a parallel `json8` builtin with the same uage. See [J8
|
14 | Notation](j8-notation.html) for details on the encoding.
|
15 |
|
16 | <div id="toc">
|
17 | </div>
|
18 |
|
19 | The `json` **builtin** has `read` and `write` subcommands, which convert
|
20 | between serialized data languages and in-memory data structures.
|
21 |
|
22 | YSH data structures are like those in Python and JavaScript, so this
|
23 | correspondence is natural.
|
24 |
|
25 | ## `json read` parses from `stdin`
|
26 |
|
27 | Usage:
|
28 |
|
29 | json read (PLACE?)
|
30 | json8 read (PLACE?)
|
31 |
|
32 | Examples:
|
33 |
|
34 | $ cat stats.json
|
35 | {"count": 42}
|
36 |
|
37 | # Read from a file. By default, the variable _reply is written.
|
38 | $ json read < stats.json
|
39 |
|
40 | # Use = to pretty print an expression
|
41 | $ = _reply
|
42 | (Dict) {'count': 42}
|
43 |
|
44 | Specify a place to put the data:
|
45 |
|
46 | $ json read (&myvar) < stats.json
|
47 |
|
48 | $ = myvar
|
49 | (Dict) {'count': 42}
|
50 |
|
51 | Use it in a pipeline:
|
52 |
|
53 | # 'json read' is valid at the end of a pipeline (because YSH implements
|
54 | # shopt -s lastpipe)
|
55 | $ echo '{"count": 42}' | json read (&myvar)
|
56 |
|
57 | Failure with invalid input data:
|
58 |
|
59 | $ echo '[ "incomplete"' | json read (&myvar) < invalid.json
|
60 | [ "incomplete"
|
61 | ^
|
62 | json read: premature EOF
|
63 |
|
64 | $ echo $?
|
65 | 1
|
66 |
|
67 | ## `json write` prints to `stdout`
|
68 |
|
69 | Usage:
|
70 |
|
71 | json write (EXPR, space=2)
|
72 |
|
73 | EXPR is an expression that evaluates to a serializable object.
|
74 |
|
75 | space is the number of spaces that object and array entries are indented
|
76 | by. If it's 0 or less, then no newlines or spaces are printed.
|
77 |
|
78 | Examples:
|
79 |
|
80 | $ var d = {name: "bob", age: 42} # create Dict
|
81 |
|
82 | $ json write (d) # print as JSON, with 2 space indent
|
83 | {
|
84 | "name": "bob",
|
85 | "count": 42
|
86 | }
|
87 |
|
88 | $ json write (d, space=0) # no indent at all
|
89 | {"name":"bob","count":42}
|
90 |
|
91 | ### `write` builtin
|
92 |
|
93 | TODO
|
94 |
|
95 | write --j8 hello there
|
96 | write --json hello there # unicode replacement char
|
97 |
|
98 | ## Filter Data Structures with YSH Expressions
|
99 |
|
100 | Once your data is deserialized, you can use YSH expression to operate on it.
|
101 |
|
102 | $ echo '{"counts": [42, 99]}' | json read (&d)
|
103 |
|
104 | $ = d['counts']
|
105 | (List) [42, 99]
|
106 |
|
107 | $ = d['counts'][1]
|
108 | (Int) 99
|
109 |
|
110 | # d->counts is a synonym for d["counts"]
|
111 | $ json write (d->counts)
|
112 | [
|
113 | 42,
|
114 | 99
|
115 | ]
|
116 |
|
117 | Note: It may more efficient to filter large data structures with tools like
|
118 | `jq` first.
|
119 |
|
120 | ## Other Data Structures Can Be Printed as JSON
|
121 |
|
122 | YSH arrays and shell arrays both serialize to a list of strings:
|
123 |
|
124 | $ declare sharray=( foo.txt *.py )
|
125 | $ json write (sharray)
|
126 | [
|
127 | "foo.txt",
|
128 | "one.py",
|
129 | "two.py"
|
130 | ]
|
131 |
|
132 | $ var oilarray = :| foo.txt *.py |
|
133 | $ json write (oilarray)
|
134 | [
|
135 | "foo.txt",
|
136 | "one.py",
|
137 | "two.py"
|
138 | ]
|
139 |
|
140 | Bash-style associative arrays are printed like `Dict[Str, Str]`:
|
141 |
|
142 | $ declare -A assoc=(["key"]=value)
|
143 | $ json write (assoc)
|
144 | {
|
145 | "key": "value"
|
146 | }
|
147 |
|