4 # src["hello"] = "world"
5 # json_save("test.json", src)
6 # json_load("test.json", dst)
11 # object: { string : value, .. }
12 # array: [ value, .. ]
20 # any-Unicode-character-except-"-or-\-or-control-character
32 function json_gettype(value, key, sort, n, i)
38 n = asorti(value, sort)
39 for (i = 0; i < n; i++)
44 if (value == 0 && value == "")
46 if (value == value + 0)
48 if (value == value "")
54 function json_join(array, sep, i, str)
57 for (i = 1; i < length(array); i++)
58 str = str sep array[i]
62 function json_copy(dst, to, src, key)
68 json_copy(dst[to], key, src[key])
77 function json_write_value(value, pad)
79 switch (json_gettype(value)) {
80 case "object": return json_write_object(value, pad)
81 case "array": return json_write_array(value, pad)
82 case "number": return json_write_number(value)
83 case "string": return json_write_string(value)
84 case "null": return "null"
85 default: return "error"
89 function json_write_object(object, pad, n, i, sort, key, val, data, len, max)
91 n = asorti(object, sort)
92 for (i = 0; i < n; i++) {
93 key = json_write_string(sort[i+1])
94 if (length(key) > max)
97 for (i = 0; i < n; i++) {
98 key = json_write_string(sort[i+1])
99 val = json_write_value(object[sort[i+1]],
100 sprintf("%s %"max"s ", pad, ""))
101 data[i] = sprintf("%-"(max+1)"s %s", key":", val)
103 return "{ " json_join(data, ",\n " pad) " }"
106 function json_write_array(array, pad, i, data)
108 for (i = 0; i < length(array); i++)
109 data[i] = json_write_value(array[i], pad " ")
110 return "[ " json_join(data, ",\n " pad) " ]"
113 function json_write_number(number)
118 function json_write_string(string)
120 gsub(/\\/, "\\\\", string)
121 gsub(/"/, "\\\"", string)
122 gsub(/\b/, "\\b", string)
123 gsub(/\f/, "\\f", string)
124 gsub(/\n/, "\\n", string)
125 gsub(/\r/, "\\r", string)
126 gsub(/\t/, "\\t", string)
128 return "\"" string "\""
133 function json_tokenize(str, tokens, i, line, items, table, type, found)
135 table["term"] = "^[\\[\\]{}:,]"
136 table["str"] = "^\"([^\\\\\"]|\\\\.)*\""
137 table["num"] = "^[+-]?[0-9]+(.[0-9]+)?"
138 table["var"] = "^(true|false|null)"
139 table["space"] = "^[ \\t]+"
140 table["line"] = "^\n"
143 while (length(str) > 0) {
145 for (type in table) {
146 #print "match: str=["str"] type="type" regex=/"table[type]"/"
147 if (match(str, table[type], items) > 0) {
148 #print " len="RLENGTH" item=["items[0]"]"
153 if (type != "space" && type != "line") {
154 tokens[i]["line"] = line
155 tokens[i]["type"] = type
156 tokens[i]["text"] = items[0]
159 str = substr(str, RLENGTH+1)
165 debug("line " line ": error tokenizing")
170 #for (i = 0; i < length(tokens); i++)
171 # printf "%-3s %-5s [%s]\n", i":",
172 # tokens[i]["type"], tokens[i]["text"]
177 function json_parse_value(tokens, i, value, key, line, type, text)
180 if (!depth) depth = 0
182 line = tokens[i]["line"]
183 type = tokens[i]["type"]
184 text = tokens[i]["text"]
185 #printf "parse %d: i=%-2d type=%-3s text=%s\n", depth, i, type, text
187 case "{": i = json_parse_object(tokens, i, value, key); break
188 case "[": i = json_parse_array(tokens, i, value, key); break
189 case "str": i = json_parse_string(tokens, i, value, key); break
190 case "num": i = json_parse_number(tokens, i, value, key); break
191 case "var": i = json_parse_var(tokens, i, value, key); break
192 default: debug("line "line": error type="type" text="text); return 0
198 function json_parse_object(tokens, i, value, key, object, k, v)
200 if (tokens[i++]["text"] != "{")
203 if (tokens[i]["text"] != "}") {
207 if (!(i=json_parse_value(tokens, i, k, 0)))
209 if (tokens[i++]["text"] != ":")
211 if (!(i=json_parse_value(tokens, i, v, 0)))
213 json_copy(object, k[0], v[0])
214 } while (tokens[i++]["text"] == ",")
218 if (tokens[i++]["text"] != "}")
221 json_copy(value, key, object)
225 function json_parse_array(tokens, i, value, key, array, k, v)
227 if (tokens[i++]["text"] != "[")
230 if (tokens[i]["text"] != "]") {
233 if (!(i=json_parse_value(tokens, i, v, 0)))
235 json_copy(array, k++, v[0])
236 } while (tokens[i++]["text"] == ",")
240 if (tokens[i++]["text"] != "]")
243 json_copy(value, key, array)
247 function json_parse_number(tokens, i, value, key, text)
249 text = tokens[i++]["text"]
250 json_copy(value, key, text + 0)
251 #print "parse_number: " (text + 0)
255 function json_parse_string(tokens, i, value, key, text)
257 text = tokens[i++]["text"]
259 text = len == 2 ? "" : substr(text, 2, len-2)
261 gsub(/\\\\/, "\\", text)
262 gsub(/\\"/, "\"", text)
263 gsub(/\\b/, "\b", text)
264 gsub(/\\f/, "\f", text)
265 gsub(/\\n/, "\n", text)
266 gsub(/\\r/, "\r", text)
267 gsub(/\\t/, "\t", text)
269 json_copy(value, key, text)
270 #print "parse_string: [" text "]"
274 function json_parse_var(tokens, i, value, key, text, null)
276 switch (tokens[i++]["text"]) {
277 case "true": json_copy(value, key, 1==1); break;
278 case "false": json_copy(value, key, 1==2); break;
279 case "null": json_copy(value, key, null); break;
281 #print "parse_var: " text " -> " text == "true"
287 function json_decode(string, var, tokens, data, key)
289 if (!json_tokenize(string, tokens))
291 if (!json_parse_value(tokens, 0, data, 0))
293 if (!isarray(data[0]))
296 json_copy(var, key, data[0][key])
300 function json_encode(var, pad)
302 return json_write_value(var, pad)
306 function json_load(file, var, line, string)
309 while ((getline line < file) > 0)
310 string = string line "\n"
311 return json_decode(string, var)
314 function json_save(file, var, cmd, tmp)
316 cmd = "mktemp " file ".XXX"
319 print json_encode(var) > tmp
321 system("mv " tmp " " file)
326 function json_test_write()
328 print "Testing JSON Write:"
337 json_copy(mix, "number", num);
338 json_copy(mix, "str", str);
339 json_copy(mix, "arr", arr);
340 json_copy(mix, "obj", obj);
341 json_copy(dub, "first", mix);
342 json_copy(dub, "second", mix);
343 print json_encode(num)
344 print json_encode(str)
345 print json_encode(arr)
346 print json_encode(obj)
347 print json_encode(mix)
348 print json_encode(dub)
351 function json_test_read()
353 print "Testing JSON Read:"
355 json_decode("[8, \"abc\", 9]", array);
356 print json_encode(array)
358 json_decode("{\"abc\": 1, \"def\": 2}", array)
359 print json_encode(array)
361 json = "{ \"first\": { \"arr\": [ \"\", \n" \
367 " \"number\": 42, \n" \
368 " \"eobj\": [ ], \n" \
369 " \"earr\": { }, \n" \
370 " \"obj\": { \"A\": \"a!\", \n" \
371 " \"B\": \"b!\", \n" \
372 " \"C\": \"c!\" }, \n" \
373 " \"str\": \"hello, world\" }, \n" \
374 " \"second\": { \"arr\": [ \"zero\", \n" \
377 " \"\\\"\t\r\b\" ], \n" \
378 " \"number\": 42, \n" \
379 " \"obj\": { \"A\": \"a!\", \n" \
380 " \"B\": \"b!\", \n" \
381 " \"C\": \"c!\" }, \n" \
382 " \"str\": \"hello, world\" } }\n"
384 json_decode(json, array)
385 print json_encode(array)
388 function json_test_files()
390 print "Testing JSON Files:"
391 print "load: [" json_load("email.txt", mail) "]"
392 print "mail: " json_encode(mail, " ")
393 mail["andy753421"] = "andy753421@gmail.com"
394 mail["andy"] = "andy@gmail.com"
395 mail["somebody"] = "foo@example.com"
396 print "mail: " json_encode(mail, " ")
397 print "save: [" json_save("email.txt", mail) "]"