-
Notifications
You must be signed in to change notification settings - Fork 21
/
Copy pathjson.swim
255 lines (175 loc) · 7.59 KB
/
json.swim
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
JSON
====
JSON for Bash
<badge travis ingydotnet/json-bash>
= Synopsis
source json.bash
json='{"name":"Jason","friends":["Jimmy","Joe"]}'
JSON.load "$json"
joe=$(JSON.get /friends/1)
JSON.put /friends/2 Jeff
new_json=$(JSON.dump)
= Description
The `json.bash` library provides functions for loading, manipulating and
dumping JSON data.
Bash doesn't have nestable hashes and arrays to load JSON data into.
This library provides a different data model called a "linear tree". A
linear tree is simply a sequence of text lines, each containing a key-path
and a leaf-value (separated by a tab):
/key/path<HARD-TAB>"leaf value"
Thus this JSON:
{
"name": {
"first": "Jimmy",
"last": "James"
},
"list": [
"A string",
42,
[ true, false, null ]
]
}
Would be loaded as this linear tree:
/name/first "Jimmy"
/name/last "James"
/list/0 "A string"
/list/1 42
/list/2/0 true
/list/2/1 false
/list/2/2 null
Since Bash has many tools for searching and manipulating text, the linear form
works fairly well for common JSON data operations.
= Installation
Just run:
make install
This may require `sudo` permission.
By default, this will install:
/usr/local/lib/bash/test-simple.bash
/usr/local/share/man/man1/test-simple.1
You can change the install locations with these environment variables:
* `PREFIX` - default is `/usr/local`
* `INSTALL_LIB`
* `INSTALL_MAN`
Run `make help` to see all the `make` targets that are available.
= API Functions
The library contains functions to *load* JSON to the linear form and to *dump*
that form back into JSON. It also has functions to retrieve, modify, add and
remove data from the linear form.
- `JSON.load [ <json-string> [<linear-var-name>]]`
This function takes JSON as input and generates a linear tree as output.
With no arguments, input is read from stdin and output is written to stdout.
With one argument, the input is provided as a string argument and the output
is stored in an internal cache variable. With two arguments the input is
again provided as a string argument, and the output is copied into the
variable name provided.
- `JSON.dump [<linear-var-name>]`
This function takes a linear tree as input and generates JSON as output.
With no arguments, input is read from stdin. With one argument, input is
taken from the provided variable name. To use the internal cache, use `-` as
the variable name. Output is always written to stdout. Formatting of
the output can be set using JSON.style (see below).
- `JSON.style minimal|normal|pretty [<indent-string>]`
This function sets style of output formatting for all subsequent calls to
JSON.dump.
There are three different styles available:
* `minimal` - single line, no unnecessary whitespace
* `normal` - single line, keys and values separated by single space
* `pretty` - one value per line, indented
Before first call to this function, the style is set to "normal".
The second argument is only honored for "pretty" formatting style.
- `JSON.get [-a|-s|-b|-n|-z] <key-path> [<linear-var-name>]`
This function takes a key path and returns the corresponding value. If the
key is found, the exit status is 0, otherwise it is 1. If the value is a
string, it will be enclosed in double quotes. Otherwise it will be a number
or the unquoted strings: `true`, `false` or `null`.
With just the one required argument, the linear tree will be obtained from
stdin. Otherwise it can be provided with a variable name (or `-` for the
cache). The value (if any) is written to stdout.
See FLAGS below for an explanation of the flag options.
- `JSON.keys <key-path> [<linear-var-name>]`
This function takes a key path and returns the keys of the corresponding
object, one per line. If the key is not found or the value of the
key is not an object, it will return nothing.
- `JSON.object <key-path> [<linear-var-name>]`
This function takes a key path and returns the corresponding object.
If the key is not found, it will return nothing.
- `JSON.put [-s|-b|-n|-z] <key-path> <new-value> [<linear-var-name>]`
This function adds a path/value pair to the linear tree. If the path already
exists, the value will be replaced, otherwise it will be added.
With just the two required arguments, the linear tree will be obtained from
stdin. Otherwise it can be provided with a variable name (or `-` for the
cache). Nothing will be written to stdout and the exit status will always be
0.
- `JSON.del <key-path> <new-value> [<linear-var-name>]`
This function removes a path/value pair from the linear tree, if it exists.
With just the one required argument, the linear tree will be obtained from
stdin. Otherwise it can be provided with a variable name (or `-` for the
cache). Nothing will be written to stdout and the exit status will always be
0.
Heuristics will be used to determine what type the value is. The -s flag
indicates the value is a string, the -n flag indicates a number,the -b flag
indicates a boolean and the -z flag indicates a null value.
- `JSON.cache [<linear-var-name>]`
Outputs the value of the internal linear tree cache string.
With no arguments, the value is written to stdout. With one argument, the
value is copied to the variable name provided.
= Flags
The command flags `-a`, `-s`, `-n`, `-b` and `-z` indicate the *type* of value
provided or expected, and they refer to Any, String, Number, Boolean and Null
respectively. If the type of data doesn't look like the type indicated by the
flag, the command will return with a status code of 2.
If `-a` is used, the double quotes at each end (if any) will be removed for a
`JSON.get`.
If `-s` is used and the data is a string, the double quotes will be removed for
a `JSON.get` or added for a `JSON.put`.
The `-n` flag requires no value transformation, but it will cause the command
to fail (status 2) if the value is not a number.
If `-b` is used for a `JSON.get`, true will become 0 and false will become 1.
`JSON.put` will do the reverse. This follows Bash's idea of using 0 for a
successful return code.
The `-z` flag on a `JSON.get` will turn `null` into the empty string, and for a
`JSON.put` will turn any value into `null`.
= Examples
# Load JSON to linear tree
JSON.load "$(< file.json)" tree
# or:
tree=$(cat file.json | JSON.load)
# Get a value
first_name=$(JSON.get /name/first tree)
# or:
first_name=$(echo "$tree" | JSON.get /name/first)
# Change a value
JSON.put /name/first Jimmy tree
# or:
tree=(echo "$tree" | JSON.put /name/first Jimmy)
# Delete a value
JSON.del /name/middle tree
# or:
tree=(echo "$tree" | JSON.del /name/middle)
# Dump a linear tree to JSON
JSON.dump tree > new-file.json
# or:
echo "$tree" | JSON.dump > new-file.json
= Problems
This library is meant to be useful for solving common problems involving JSON.
However, without the native JSON object model in Bash, it becomes problematic
the further you stray from the norm.
Here is a list of known issues. Some may be addressed, some are very likely to
stay out of scope:
* No support for empty arrays and empty objects.
* No support for key-paths that refer to objects or arrays.
* No support for common array operations like `push`, `pop`, `splice`, etc.
= Todo
* Support object keys that:
* Contain whitespace
* Consist of all digit characters
* Contain backslashes
* Implement JSON.dump
= Status
Please report any issues to https://github.com/ingydotnet/json-bash/issues
Or find me on [email protected].
= Author
Written by Ingy döt Net <[email protected]>
= Copyright & License
Copyright 2013-2016 Ingy döt Net
The MIT License (MIT)