2 # object: { string : value, .. }
11 # any-Unicode-character-except-"-or-\-or-control-character
24 function json_gettype(value, key, sort, n, i)
30 n = asorti(value, sort)
31 for (i = 0; i < n; i++)
36 if (value == value + 0)
38 if (value == value "")
44 function json_join(array, sep, i, str)
47 for (i = 1; i < length(array); i++)
48 str = str sep array[i]
52 function json_copy(dst, to, src, key)
58 json_copy(dst[to], key, src[key])
67 function json_write_value(value, pad)
69 switch (json_gettype(value)) {
70 case "object": return json_write_object(value, pad)
71 case "array": return json_write_array(value, pad)
72 case "number": return json_write_number(value)
73 case "string": return json_write_string(value)
74 default: return "error"
78 function json_write_object(object, pad, n, i, sort, key, val, data, len, max)
80 n = asorti(object, sort)
81 for (i = 0; i < n; i++) {
82 key = json_write_string(sort[i+1])
83 if (length(key) > max)
86 for (i = 0; i < n; i++) {
87 key = json_write_string(sort[i+1])
88 val = json_write_value(object[sort[i+1]],
89 sprintf("%s %"max"s ", pad, ""))
90 data[i] = sprintf("%-"(max+1)"s %s", key":", val)
92 return "{ " json_join(data, ",\n " pad) " }"
95 function json_write_array(array, pad, i, data)
97 for (i = 0; i < length(array); i++)
98 data[i] = json_write_value(array[i], pad " ")
99 return "[ " json_join(data, ",\n " pad) " ]"
102 function json_write_number(number)
107 function json_write_string(string)
109 # todo: special characters
110 return "\"" string "\""
115 function json_tokenize(str, tokens, i, items, table, type, found)
117 table["term"] = "^[\\[\\]{}:,]"
118 table["str"] = "^\"[^\"]*\""
119 table["num"] = "^[0-9]+"
120 table["var"] = "^(true|false|null)"
121 table["space"] = "^[ \\t\\n]+"
123 while (length(str) > 0) {
125 for (type in table) {
126 #print "match: str=["str"] type="type" regex=/"table[type]"/"
127 if (match(str, table[type], items) > 0) {
128 #print " len="RLENGTH" item=["items[0]"]"
131 if (type != "space") {
132 tokens[i]["type"] = type
133 tokens[i]["text"] = items[0]
136 str = substr(str, RLENGTH+1)
142 debug("error tokenizing")
148 #for (i = 0; i < length(tokens); i++)
149 # printf "%-3s %-5s [%s]\n", i":",
150 # tokens[i]["type"], tokens[i]["text"]
153 function json_parse_value(tokens, i, value, key, type, text)
156 if (!depth) depth = 0
158 type = tokens[i]["type"]
159 text = tokens[i]["text"]
160 #printf "parse %d: i=%-2d type=%-3s text=%s\n", depth, i, type, text
162 case "{": i = json_parse_object(tokens, i, value, key); break
163 case "[": i = json_parse_array(tokens, i, value, key); break
164 case "str": i = json_parse_string(tokens, i, value, key); break
165 case "num": i = json_parse_number(tokens, i, value, key); break
166 case "var": i = json_parse_var(tokens, i, value, key); break
167 default: debug("error: type="type" text="text); return 0
173 function json_parse_object(tokens, i, value, key, object, k, v)
175 if (tokens[i++]["text"] != "{")
181 if (!(i=json_parse_value(tokens, i, k, 0)))
183 if (tokens[i++]["text"] != ":")
185 if (!(i=json_parse_value(tokens, i, v, 0)))
187 json_copy(object, k[0], v[0])
188 } while (tokens[i++]["text"] == ",")
191 if (tokens[i++]["text"] != "}")
194 json_copy(value, key, object)
198 function json_parse_array(tokens, i, value, key, array, k, v)
200 #print "parse_array: .."
201 if (tokens[i++]["text"] != "[")
206 if (!(i=json_parse_value(tokens, i, v, 0)))
208 json_copy(array, k++, v[0])
209 } while (tokens[i++]["text"] == ",")
212 if (tokens[i++]["text"] != "]")
215 json_copy(value, key, array)
219 function json_parse_number(tokens, i, value, key, text)
221 text = tokens[i++]["text"]
222 json_copy(value, key, text + 0)
223 #print "parse_number: " (text + 0)
227 function json_parse_string(tokens, i, value, key, text)
229 text = tokens[i++]["text"]
230 text = substr(text, 2, length(text)-2)
231 json_copy(value, key, text)
232 #print "parse_string: " text
236 function json_parse_var(tokens, i, value, key, text)
238 text = tokens[i++]["text"]
239 json_copy(value, key, text == "true")
240 #print "parse_var: " text " -> " text == "true"
246 function json_load(file, var, line, text, tokens, data, key)
248 while ((getline line < file) > 0)
251 if (!json_tokenize(text, tokens))
253 if (!json_parse_value(tokens, 0, data, 0))
255 if (!isarray(data[0]))
258 json_copy(var, key, data[0][key])
261 function json_save(file, var, cmd, tmp)
263 cmd = "mktemp " file ".XXX"
266 print json_write_value(var) > tmp
268 system("mv " tmp " " file)
273 function json_test_write()
283 json_copy(mix, "number", num);
284 json_copy(mix, "str", str);
285 json_copy(mix, "arr", arr);
286 json_copy(mix, "obj", obj);
287 json_copy(dub, "first", mix);
288 json_copy(dub, "second", mix);
289 print json_write_value(num)
290 print json_write_value(str)
291 print json_write_value(arr)
292 print json_write_value(obj)
293 print json_write_value(mix)
294 print json_write_value(dub)
297 function json_test_read()
299 json_tokenize("[8, \"abc\", 9]", tokens)
300 json_parse_value(tokens, 0, array, 0)
301 json_print write_value(array[0])
303 json_tokenize("{\"abc\": 1, \"def\": 2}", tokens)
304 json_parse_value(tokens, 0, array, 0)
305 json_print write_value(array[0])
307 json = "{ \"first\": { \"arr\": [ \"zero\", " \
310 " \"number\": 42, " \
311 " \"obj\": { \"A\": \"a!\", " \
313 " \"C\": \"c!\" }, " \
314 " \"str\": \"hello, world\" }, " \
315 " \"second\": { \"arr\": [ \"zero\", " \
318 " \"number\": 42, " \
319 " \"obj\": { \"A\": \"a!\", " \
321 " \"C\": \"c!\" }, " \
322 " \"str\": \"hello, world\" } }"
324 json_tokenize(json, tokens)
325 json_parse_value(tokens, 0, array, 0)
326 print json_write_value(array[0])
329 function json_test_files()
331 print "load: [" json_load("email.txt", mail) "]"
332 print "mail: " json_write_value(mail, " ")
333 mail["andy753421"] = "andy753421@gmail.com"
334 mail["andy"] = "andy@gmail.com"
335 mail["somebody"] = "foo@example.com"
336 print "mail: " json_write_value(mail, " ")
337 print "save: [" json_save("email.txt", mail) "]"