2 # object: { string : value, .. }
11 # any-Unicode-character-except-"-or-\-or-control-character
23 function json_gettype(value, key, sort, n, i)
29 n = asorti(value, sort)
30 for (i = 0; i < n; i++)
35 if (value == 0 && value == "")
37 if (value == value + 0)
39 if (value == value "")
45 function json_join(array, sep, i, str)
48 for (i = 1; i < length(array); i++)
49 str = str sep array[i]
53 function json_copy(dst, to, src, key)
59 json_copy(dst[to], key, src[key])
68 function json_write_value(value, pad)
70 switch (json_gettype(value)) {
71 case "object": return json_write_object(value, pad)
72 case "array": return json_write_array(value, pad)
73 case "number": return json_write_number(value)
74 case "string": return json_write_string(value)
75 case "null": return "null"
76 default: return "error"
80 function json_write_object(object, pad, n, i, sort, key, val, data, len, max)
82 n = asorti(object, sort)
83 for (i = 0; i < n; i++) {
84 key = json_write_string(sort[i+1])
85 if (length(key) > max)
88 for (i = 0; i < n; i++) {
89 key = json_write_string(sort[i+1])
90 val = json_write_value(object[sort[i+1]],
91 sprintf("%s %"max"s ", pad, ""))
92 data[i] = sprintf("%-"(max+1)"s %s", key":", val)
94 return "{ " json_join(data, ",\n " pad) " }"
97 function json_write_array(array, pad, i, data)
99 for (i = 0; i < length(array); i++)
100 data[i] = json_write_value(array[i], pad " ")
101 return "[ " json_join(data, ",\n " pad) " ]"
104 function json_write_number(number)
109 function json_write_string(string)
111 # todo: special characters
112 return "\"" string "\""
117 function json_tokenize(str, tokens, i, line, items, table, type, found)
119 table["term"] = "^[\\[\\]{}:,]"
120 table["str"] = "^\"[^\"]*\""
121 table["num"] = "^[+-]?[0-9]+(.[0-9]+)?"
122 table["var"] = "^(true|false|null)"
123 table["space"] = "^[ \\t]+"
124 table["line"] = "^\n"
127 while (length(str) > 0) {
129 for (type in table) {
130 #print "match: str=["str"] type="type" regex=/"table[type]"/"
131 if (match(str, table[type], items) > 0) {
132 #print " len="RLENGTH" item=["items[0]"]"
137 if (type != "space" && type != "line") {
138 tokens[i]["line"] = line
139 tokens[i]["type"] = type
140 tokens[i]["text"] = items[0]
143 str = substr(str, RLENGTH+1)
149 debug("line " line ": error tokenizing")
155 #for (i = 0; i < length(tokens); i++)
156 # printf "%-3s %-5s [%s]\n", i":",
157 # tokens[i]["type"], tokens[i]["text"]
160 function json_parse_value(tokens, i, value, key, line, type, text)
163 if (!depth) depth = 0
165 line = tokens[i]["line"]
166 type = tokens[i]["type"]
167 text = tokens[i]["text"]
168 #printf "parse %d: i=%-2d type=%-3s text=%s\n", depth, i, type, text
170 case "{": i = json_parse_object(tokens, i, value, key); break
171 case "[": i = json_parse_array(tokens, i, value, key); break
172 case "str": i = json_parse_string(tokens, i, value, key); break
173 case "num": i = json_parse_number(tokens, i, value, key); break
174 case "var": i = json_parse_var(tokens, i, value, key); break
175 default: debug("line "line": error type="type" text="text); return 0
181 function json_parse_object(tokens, i, value, key, object, k, v)
183 if (tokens[i++]["text"] != "{")
186 if (tokens[i]["text"] != "}") {
190 if (!(i=json_parse_value(tokens, i, k, 0)))
192 if (tokens[i++]["text"] != ":")
194 if (!(i=json_parse_value(tokens, i, v, 0)))
196 json_copy(object, k[0], v[0])
197 } while (tokens[i++]["text"] == ",")
201 if (tokens[i++]["text"] != "}")
204 json_copy(value, key, object)
208 function json_parse_array(tokens, i, value, key, array, k, v)
210 if (tokens[i++]["text"] != "[")
213 if (tokens[i]["text"] != "]") {
216 if (!(i=json_parse_value(tokens, i, v, 0)))
218 json_copy(array, k++, v[0])
219 } while (tokens[i++]["text"] == ",")
223 if (tokens[i++]["text"] != "]")
226 json_copy(value, key, array)
230 function json_parse_number(tokens, i, value, key, text)
232 text = tokens[i++]["text"]
233 json_copy(value, key, text + 0)
234 #print "parse_number: " (text + 0)
238 function json_parse_string(tokens, i, value, key, text)
240 text = tokens[i++]["text"]
242 text = len == 2 ? "" : substr(text, 2, len-2)
243 json_copy(value, key, text)
244 #print "parse_string: [" text "]"
248 function json_parse_var(tokens, i, value, key, text, null)
250 switch (tokens[i++]["text"]) {
251 case "true": json_copy(value, key, 1==1); break;
252 case "false": json_copy(value, key, 1==2); break;
253 case "null": json_copy(value, key, null); break;
255 #print "parse_var: " text " -> " text == "true"
261 function json_load(file, var, line, text, tokens, data, key)
263 while ((getline line < file) > 0)
266 if (!json_tokenize(text, tokens))
268 if (!json_parse_value(tokens, 0, data, 0))
270 if (!isarray(data[0]))
273 json_copy(var, key, data[0][key])
277 function json_save(file, var, cmd, tmp)
279 cmd = "mktemp " file ".XXX"
282 print json_write_value(var) > tmp
284 system("mv " tmp " " file)
289 function json_test_write()
299 json_copy(mix, "number", num);
300 json_copy(mix, "str", str);
301 json_copy(mix, "arr", arr);
302 json_copy(mix, "obj", obj);
303 json_copy(dub, "first", mix);
304 json_copy(dub, "second", mix);
305 print json_write_value(num)
306 print json_write_value(str)
307 print json_write_value(arr)
308 print json_write_value(obj)
309 print json_write_value(mix)
310 print json_write_value(dub)
313 function json_test_read()
315 json_tokenize("[8, \"abc\", 9]", tokens)
316 json_parse_value(tokens, 0, array, 0)
317 print json_write_value(array[0])
319 json_tokenize("{\"abc\": 1, \"def\": 2}", tokens)
320 json_parse_value(tokens, 0, array, 0)
321 print json_write_value(array[0])
323 json = "{ \"first\": { \"arr\": [ \"\", \n" \
329 " \"number\": 42, \n" \
330 " \"eobj\": [ ], \n" \
331 " \"earr\": { }, \n" \
332 " \"obj\": { \"A\": \"a!\", \n" \
333 " \"B\": \"b!\", \n" \
334 " \"C\": \"c!\" }, \n" \
335 " \"str\": \"hello, world\" }, \n" \
336 " \"second\": { \"arr\": [ \"zero\", \n" \
339 " \"number\": 42, \n" \
340 " \"obj\": { \"A\": \"a!\", \n" \
341 " \"B\": \"b!\", \n" \
342 " \"C\": \"c!\" }, \n" \
343 " \"str\": \"hello, world\" } }\n"
345 json_tokenize(json, tokens)
346 json_parse_value(tokens, 0, array, 0)
347 print json_write_value(array[0])
350 function json_test_files()
352 print "load: [" json_load("email.txt", mail) "]"
353 print "mail: " json_write_value(mail, " ")
354 mail["andy753421"] = "andy753421@gmail.com"
355 mail["andy"] = "andy@gmail.com"
356 mail["somebody"] = "foo@example.com"
357 print "mail: " json_write_value(mail, " ")
358 print "save: [" json_save("email.txt", mail) "]"