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, 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\\n]+"
125 while (length(str) > 0) {
127 for (type in table) {
128 #print "match: str=["str"] type="type" regex=/"table[type]"/"
129 if (match(str, table[type], items) > 0) {
130 #print " len="RLENGTH" item=["items[0]"]"
133 if (type != "space") {
134 tokens[i]["type"] = type
135 tokens[i]["text"] = items[0]
138 str = substr(str, RLENGTH+1)
144 debug("error tokenizing")
150 #for (i = 0; i < length(tokens); i++)
151 # printf "%-3s %-5s [%s]\n", i":",
152 # tokens[i]["type"], tokens[i]["text"]
155 function json_parse_value(tokens, i, value, key, type, text)
158 if (!depth) depth = 0
160 type = tokens[i]["type"]
161 text = tokens[i]["text"]
162 #printf "parse %d: i=%-2d type=%-3s text=%s\n", depth, i, type, text
164 case "{": i = json_parse_object(tokens, i, value, key); break
165 case "[": i = json_parse_array(tokens, i, value, key); break
166 case "str": i = json_parse_string(tokens, i, value, key); break
167 case "num": i = json_parse_number(tokens, i, value, key); break
168 case "var": i = json_parse_var(tokens, i, value, key); break
169 default: debug("error: type="type" text="text); return 0
175 function json_parse_object(tokens, i, value, key, object, k, v)
177 if (tokens[i++]["text"] != "{")
183 if (!(i=json_parse_value(tokens, i, k, 0)))
185 if (tokens[i++]["text"] != ":")
187 if (!(i=json_parse_value(tokens, i, v, 0)))
189 json_copy(object, k[0], v[0])
190 } while (tokens[i++]["text"] == ",")
193 if (tokens[i++]["text"] != "}")
196 json_copy(value, key, object)
200 function json_parse_array(tokens, i, value, key, array, k, v)
202 #print "parse_array: .."
203 if (tokens[i++]["text"] != "[")
208 if (!(i=json_parse_value(tokens, i, v, 0)))
210 json_copy(array, k++, v[0])
211 } while (tokens[i++]["text"] == ",")
214 if (tokens[i++]["text"] != "]")
217 json_copy(value, key, array)
221 function json_parse_number(tokens, i, value, key, text)
223 text = tokens[i++]["text"]
224 json_copy(value, key, text + 0)
225 #print "parse_number: " (text + 0)
229 function json_parse_string(tokens, i, value, key, text)
231 text = tokens[i++]["text"]
233 text = len == 2 ? "" : substr(text, 2, len-2)
234 json_copy(value, key, text)
235 #print "parse_string: [" text "]"
239 function json_parse_var(tokens, i, value, key, text, null)
241 switch (tokens[i++]["text"]) {
242 case "true": json_copy(value, key, 1==1); break;
243 case "false": json_copy(value, key, 1==2); break;
244 case "null": json_copy(value, key, null); break;
246 #print "parse_var: " text " -> " text == "true"
252 function json_load(file, var, line, text, tokens, data, key)
254 while ((getline line < file) > 0)
257 if (!json_tokenize(text, tokens))
259 if (!json_parse_value(tokens, 0, data, 0))
261 if (!isarray(data[0]))
264 json_copy(var, key, data[0][key])
268 function json_save(file, var, cmd, tmp)
270 cmd = "mktemp " file ".XXX"
273 print json_write_value(var) > tmp
275 system("mv " tmp " " file)
280 function json_test_write()
290 json_copy(mix, "number", num);
291 json_copy(mix, "str", str);
292 json_copy(mix, "arr", arr);
293 json_copy(mix, "obj", obj);
294 json_copy(dub, "first", mix);
295 json_copy(dub, "second", mix);
296 print json_write_value(num)
297 print json_write_value(str)
298 print json_write_value(arr)
299 print json_write_value(obj)
300 print json_write_value(mix)
301 print json_write_value(dub)
304 function json_test_read()
306 json_tokenize("[8, \"abc\", 9]", tokens)
307 json_parse_value(tokens, 0, array, 0)
308 print json_write_value(array[0])
310 json_tokenize("{\"abc\": 1, \"def\": 2}", tokens)
311 json_parse_value(tokens, 0, array, 0)
312 print json_write_value(array[0])
314 json = "{ \"first\": { \"arr\": [ \"\", " \
320 " \"number\": 42, " \
321 " \"obj\": { \"A\": \"a!\", " \
323 " \"C\": \"c!\" }, " \
324 " \"str\": \"hello, world\" }, " \
325 " \"second\": { \"arr\": [ \"zero\", " \
328 " \"number\": 42, " \
329 " \"obj\": { \"A\": \"a!\", " \
331 " \"C\": \"c!\" }, " \
332 " \"str\": \"hello, world\" } }"
334 json_tokenize(json, tokens)
335 json_parse_value(tokens, 0, array, 0)
336 print json_write_value(array[0])
339 function json_test_files()
341 print "load: [" json_load("email.txt", mail) "]"
342 print "mail: " json_write_value(mail, " ")
343 mail["andy753421"] = "andy753421@gmail.com"
344 mail["andy"] = "andy@gmail.com"
345 mail["somebody"] = "foo@example.com"
346 print "mail: " json_write_value(mail, " ")
347 print "save: [" json_save("email.txt", mail) "]"