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 # todo: special characters
121 return "\"" string "\""
126 function json_tokenize(str, tokens, i, line, items, table, type, found)
128 table["term"] = "^[\\[\\]{}:,]"
129 table["str"] = "^\"[^\"]*\""
130 table["num"] = "^[+-]?[0-9]+(.[0-9]+)?"
131 table["var"] = "^(true|false|null)"
132 table["space"] = "^[ \\t]+"
133 table["line"] = "^\n"
136 while (length(str) > 0) {
138 for (type in table) {
139 #print "match: str=["str"] type="type" regex=/"table[type]"/"
140 if (match(str, table[type], items) > 0) {
141 #print " len="RLENGTH" item=["items[0]"]"
146 if (type != "space" && type != "line") {
147 tokens[i]["line"] = line
148 tokens[i]["type"] = type
149 tokens[i]["text"] = items[0]
152 str = substr(str, RLENGTH+1)
158 debug("line " line ": error tokenizing")
164 #for (i = 0; i < length(tokens); i++)
165 # printf "%-3s %-5s [%s]\n", i":",
166 # tokens[i]["type"], tokens[i]["text"]
169 function json_parse_value(tokens, i, value, key, line, type, text)
172 if (!depth) depth = 0
174 line = tokens[i]["line"]
175 type = tokens[i]["type"]
176 text = tokens[i]["text"]
177 #printf "parse %d: i=%-2d type=%-3s text=%s\n", depth, i, type, text
179 case "{": i = json_parse_object(tokens, i, value, key); break
180 case "[": i = json_parse_array(tokens, i, value, key); break
181 case "str": i = json_parse_string(tokens, i, value, key); break
182 case "num": i = json_parse_number(tokens, i, value, key); break
183 case "var": i = json_parse_var(tokens, i, value, key); break
184 default: debug("line "line": error type="type" text="text); return 0
190 function json_parse_object(tokens, i, value, key, object, k, v)
192 if (tokens[i++]["text"] != "{")
195 if (tokens[i]["text"] != "}") {
199 if (!(i=json_parse_value(tokens, i, k, 0)))
201 if (tokens[i++]["text"] != ":")
203 if (!(i=json_parse_value(tokens, i, v, 0)))
205 json_copy(object, k[0], v[0])
206 } while (tokens[i++]["text"] == ",")
210 if (tokens[i++]["text"] != "}")
213 json_copy(value, key, object)
217 function json_parse_array(tokens, i, value, key, array, k, v)
219 if (tokens[i++]["text"] != "[")
222 if (tokens[i]["text"] != "]") {
225 if (!(i=json_parse_value(tokens, i, v, 0)))
227 json_copy(array, k++, v[0])
228 } while (tokens[i++]["text"] == ",")
232 if (tokens[i++]["text"] != "]")
235 json_copy(value, key, array)
239 function json_parse_number(tokens, i, value, key, text)
241 text = tokens[i++]["text"]
242 json_copy(value, key, text + 0)
243 #print "parse_number: " (text + 0)
247 function json_parse_string(tokens, i, value, key, text)
249 text = tokens[i++]["text"]
251 text = len == 2 ? "" : substr(text, 2, len-2)
252 json_copy(value, key, text)
253 #print "parse_string: [" text "]"
257 function json_parse_var(tokens, i, value, key, text, null)
259 switch (tokens[i++]["text"]) {
260 case "true": json_copy(value, key, 1==1); break;
261 case "false": json_copy(value, key, 1==2); break;
262 case "null": json_copy(value, key, null); break;
264 #print "parse_var: " text " -> " text == "true"
270 function json_load(file, var, line, text, tokens, data, key)
272 while ((getline line < file) > 0)
275 if (!json_tokenize(text, tokens))
277 if (!json_parse_value(tokens, 0, data, 0))
279 if (!isarray(data[0]))
282 json_copy(var, key, data[0][key])
286 function json_save(file, var, cmd, tmp)
288 cmd = "mktemp " file ".XXX"
291 print json_write_value(var) > tmp
293 system("mv " tmp " " file)
298 function json_test_write()
308 json_copy(mix, "number", num);
309 json_copy(mix, "str", str);
310 json_copy(mix, "arr", arr);
311 json_copy(mix, "obj", obj);
312 json_copy(dub, "first", mix);
313 json_copy(dub, "second", mix);
314 print json_write_value(num)
315 print json_write_value(str)
316 print json_write_value(arr)
317 print json_write_value(obj)
318 print json_write_value(mix)
319 print json_write_value(dub)
322 function json_test_read()
324 json_tokenize("[8, \"abc\", 9]", tokens)
325 json_parse_value(tokens, 0, array, 0)
326 print json_write_value(array[0])
328 json_tokenize("{\"abc\": 1, \"def\": 2}", tokens)
329 json_parse_value(tokens, 0, array, 0)
330 print json_write_value(array[0])
332 json = "{ \"first\": { \"arr\": [ \"\", \n" \
338 " \"number\": 42, \n" \
339 " \"eobj\": [ ], \n" \
340 " \"earr\": { }, \n" \
341 " \"obj\": { \"A\": \"a!\", \n" \
342 " \"B\": \"b!\", \n" \
343 " \"C\": \"c!\" }, \n" \
344 " \"str\": \"hello, world\" }, \n" \
345 " \"second\": { \"arr\": [ \"zero\", \n" \
348 " \"number\": 42, \n" \
349 " \"obj\": { \"A\": \"a!\", \n" \
350 " \"B\": \"b!\", \n" \
351 " \"C\": \"c!\" }, \n" \
352 " \"str\": \"hello, world\" } }\n"
354 json_tokenize(json, tokens)
355 json_parse_value(tokens, 0, array, 0)
356 print json_write_value(array[0])
359 function json_test_files()
361 print "load: [" json_load("email.txt", mail) "]"
362 print "mail: " json_write_value(mail, " ")
363 mail["andy753421"] = "andy753421@gmail.com"
364 mail["andy"] = "andy@gmail.com"
365 mail["somebody"] = "foo@example.com"
366 print "mail: " json_write_value(mail, " ")
367 print "save: [" json_save("email.txt", mail) "]"