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"] != "{")
189 if (!(i=json_parse_value(tokens, i, k, 0)))
191 if (tokens[i++]["text"] != ":")
193 if (!(i=json_parse_value(tokens, i, v, 0)))
195 json_copy(object, k[0], v[0])
196 } while (tokens[i++]["text"] == ",")
199 if (tokens[i++]["text"] != "}")
202 json_copy(value, key, object)
206 function json_parse_array(tokens, i, value, key, array, k, v)
208 if (tokens[i++]["text"] != "[")
213 if (!(i=json_parse_value(tokens, i, v, 0)))
215 json_copy(array, k++, v[0])
216 } while (tokens[i++]["text"] == ",")
219 if (tokens[i++]["text"] != "]")
222 json_copy(value, key, array)
226 function json_parse_number(tokens, i, value, key, text)
228 text = tokens[i++]["text"]
229 json_copy(value, key, text + 0)
230 #print "parse_number: " (text + 0)
234 function json_parse_string(tokens, i, value, key, text)
236 text = tokens[i++]["text"]
238 text = len == 2 ? "" : substr(text, 2, len-2)
239 json_copy(value, key, text)
240 #print "parse_string: [" text "]"
244 function json_parse_var(tokens, i, value, key, text, null)
246 switch (tokens[i++]["text"]) {
247 case "true": json_copy(value, key, 1==1); break;
248 case "false": json_copy(value, key, 1==2); break;
249 case "null": json_copy(value, key, null); break;
251 #print "parse_var: " text " -> " text == "true"
257 function json_load(file, var, line, text, tokens, data, key)
259 while ((getline line < file) > 0)
262 if (!json_tokenize(text, tokens))
264 if (!json_parse_value(tokens, 0, data, 0))
266 if (!isarray(data[0]))
269 json_copy(var, key, data[0][key])
273 function json_save(file, var, cmd, tmp)
275 cmd = "mktemp " file ".XXX"
278 print json_write_value(var) > tmp
280 system("mv " tmp " " file)
285 function json_test_write()
295 json_copy(mix, "number", num);
296 json_copy(mix, "str", str);
297 json_copy(mix, "arr", arr);
298 json_copy(mix, "obj", obj);
299 json_copy(dub, "first", mix);
300 json_copy(dub, "second", mix);
301 print json_write_value(num)
302 print json_write_value(str)
303 print json_write_value(arr)
304 print json_write_value(obj)
305 print json_write_value(mix)
306 print json_write_value(dub)
309 function json_test_read()
311 json_tokenize("[8, \"abc\", 9]", tokens)
312 json_parse_value(tokens, 0, array, 0)
313 print json_write_value(array[0])
315 json_tokenize("{\"abc\": 1, \"def\": 2}", tokens)
316 json_parse_value(tokens, 0, array, 0)
317 print json_write_value(array[0])
319 json = "{ \"first\": { \"arr\": [ \"\", \n" \
325 " \"number\": 42, \n" \
326 " \"obj\": { \"A\": \"a!\", \n" \
327 " \"B\": \"b!\", \n" \
328 " \"C\": \"c!\" }, \n" \
329 " \"str\": \"hello, world\" }, \n" \
330 " \"second\": { \"arr\": [ \"zero\", \n" \
333 " \"number\": 42, \n" \
334 " \"obj\": { \"A\": \"a!\", \n" \
335 " \"B\": \"b!\", \n" \
336 " \"C\": \"c!\" }, \n" \
337 " \"str\": \"hello, world\" } }\n"
339 json_tokenize(json, tokens)
340 json_parse_value(tokens, 0, array, 0)
341 print json_write_value(array[0])
344 function json_test_files()
346 print "load: [" json_load("email.txt", mail) "]"
347 print "mail: " json_write_value(mail, " ")
348 mail["andy753421"] = "andy753421@gmail.com"
349 mail["andy"] = "andy@gmail.com"
350 mail["somebody"] = "foo@example.com"
351 print "mail: " json_write_value(mail, " ")
352 print "save: [" json_save("email.txt", mail) "]"