X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=json.awk;h=6a8e96d675d9d3f6a0c6c4c853c1cbf46b746e4e;hb=cf7a03157ed581ada350fe636c00804c45ef74cc;hp=94c561f4b77cb7673e599e8368d023e0a963ed0e;hpb=334890a6a713664ffa4a9d7a35ec7f4bd2cd2e2b;p=~andy%2Frhawk diff --git a/json.awk b/json.awk index 94c561f..6a8e96d 100644 --- a/json.awk +++ b/json.awk @@ -1,3 +1,12 @@ +# usage: +# @include "json.awk" +# BEGIN { +# src["hello"] = "world" +# json_save("test.json", src) +# json_load("test.json", dst) +# print dst["hello"] +# } +# # value: # object: { string : value, .. } # array: [ value, .. ] @@ -108,7 +117,14 @@ function json_write_number(number) function json_write_string(string) { - # todo: special characters + gsub(/\\/, "\\\\", string) + gsub(/"/, "\\\"", string) + gsub(/\b/, "\\b", string) + gsub(/\f/, "\\f", string) + gsub(/\n/, "\\n", string) + gsub(/\r/, "\\r", string) + gsub(/\t/, "\\t", string) + return "\"" string "\"" } @@ -117,7 +133,7 @@ function json_write_string(string) function json_tokenize(str, tokens, i, line, items, table, type, found) { table["term"] = "^[\\[\\]{}:,]" - table["str"] = "^\"[^\"]*\"" + table["str"] = "^\"([^\\\\\"]|\\\\.)*\"" table["num"] = "^[+-]?[0-9]+(.[0-9]+)?" table["var"] = "^(true|false|null)" table["space"] = "^[ \\t]+" @@ -150,11 +166,12 @@ function json_tokenize(str, tokens, i, line, items, table, type, found) return 0 } } - return i #for (i = 0; i < length(tokens); i++) # printf "%-3s %-5s [%s]\n", i":", # tokens[i]["type"], tokens[i]["text"] + + return i } function json_parse_value(tokens, i, value, key, line, type, text) @@ -183,18 +200,20 @@ function json_parse_object(tokens, i, value, key, object, k, v) if (tokens[i++]["text"] != "{") return 0; - do { - delete k - delete v - if (!(i=json_parse_value(tokens, i, k, 0))) - return 0 - if (tokens[i++]["text"] != ":") - return 0 - if (!(i=json_parse_value(tokens, i, v, 0))) - return 0 - json_copy(object, k[0], v[0]) - } while (tokens[i++]["text"] == ",") - i-- + if (tokens[i]["text"] != "}") { + do { + delete k + delete v + if (!(i=json_parse_value(tokens, i, k, 0))) + return 0 + if (tokens[i++]["text"] != ":") + return 0 + if (!(i=json_parse_value(tokens, i, v, 0))) + return 0 + json_copy(object, k[0], v[0]) + } while (tokens[i++]["text"] == ",") + i-- + } if (tokens[i++]["text"] != "}") return 0; @@ -208,13 +227,15 @@ function json_parse_array(tokens, i, value, key, array, k, v) if (tokens[i++]["text"] != "[") return 0; - do { - delete v - if (!(i=json_parse_value(tokens, i, v, 0))) - return 0 - json_copy(array, k++, v[0]) - } while (tokens[i++]["text"] == ",") - i-- + if (tokens[i]["text"] != "]") { + do { + delete v + if (!(i=json_parse_value(tokens, i, v, 0))) + return 0 + json_copy(array, k++, v[0]) + } while (tokens[i++]["text"] == ",") + i-- + } if (tokens[i++]["text"] != "]") return 0; @@ -236,6 +257,15 @@ function json_parse_string(tokens, i, value, key, text) text = tokens[i++]["text"] len = length(text); text = len == 2 ? "" : substr(text, 2, len-2) + + gsub(/\\\\/, "\\", text) + gsub(/\\"/, "\"", text) + gsub(/\\b/, "\b", text) + gsub(/\\f/, "\f", text) + gsub(/\\n/, "\n", text) + gsub(/\\r/, "\r", text) + gsub(/\\t/, "\t", text) + json_copy(value, key, text) #print "parse_string: [" text "]" return i @@ -253,13 +283,10 @@ function json_parse_var(tokens, i, value, key, text, null) } -# Nice API? -function json_load(file, var, line, text, tokens, data, key) +# String API +function json_decode(string, var, tokens, data, key) { - while ((getline line < file) > 0) - text = text line - close(file) - if (!json_tokenize(text, tokens)) + if (!json_tokenize(string, tokens)) return "" if (!json_parse_value(tokens, 0, data, 0)) return "" @@ -270,12 +297,25 @@ function json_load(file, var, line, text, tokens, data, key) return 1 } +function json_encode(var, pad) +{ + return json_write_value(var, pad) +} + +# File API +function json_load(file, var, line, string) +{ + while ((getline line < file) > 0) + string = string line "\n" + return json_decode(string, var) +} + function json_save(file, var, cmd, tmp) { cmd = "mktemp " file ".XXX" cmd | getline tmp close(cmd) - print json_write_value(var) > tmp + print json_encode(var) > tmp close(tmp) system("mv " tmp " " file) } @@ -284,6 +324,7 @@ function json_save(file, var, cmd, tmp) # Test functions function json_test_write() { + print "Testing JSON Write:" num = 42 str = "hello, world" arr[0] = "zero" @@ -298,23 +339,23 @@ function json_test_write() json_copy(mix, "obj", obj); json_copy(dub, "first", mix); json_copy(dub, "second", mix); - print json_write_value(num) - print json_write_value(str) - print json_write_value(arr) - print json_write_value(obj) - print json_write_value(mix) - print json_write_value(dub) + print json_encode(num) + print json_encode(str) + print json_encode(arr) + print json_encode(obj) + print json_encode(mix) + print json_encode(dub) } function json_test_read() { - json_tokenize("[8, \"abc\", 9]", tokens) - json_parse_value(tokens, 0, array, 0) - print json_write_value(array[0]) + print "Testing JSON Read:" + + json_decode("[8, \"abc\", 9]", array); + print json_encode(array) - json_tokenize("{\"abc\": 1, \"def\": 2}", tokens) - json_parse_value(tokens, 0, array, 0) - print json_write_value(array[0]) + json_decode("{\"abc\": 1, \"def\": 2}", array) + print json_encode(array) json = "{ \"first\": { \"arr\": [ \"\", \n" \ " -1, \n" \ @@ -323,32 +364,35 @@ function json_test_read() " false, \n" \ " null ], \n" \ " \"number\": 42, \n" \ + " \"eobj\": [ ], \n" \ + " \"earr\": { }, \n" \ " \"obj\": { \"A\": \"a!\", \n" \ " \"B\": \"b!\", \n" \ " \"C\": \"c!\" }, \n" \ " \"str\": \"hello, world\" }, \n" \ " \"second\": { \"arr\": [ \"zero\", \n" \ " \"one\", \n" \ - " \"two\" ], \n" \ + " \"two\", \n" \ + " \"\\\"\t\r\b\" ], \n" \ " \"number\": 42, \n" \ " \"obj\": { \"A\": \"a!\", \n" \ " \"B\": \"b!\", \n" \ " \"C\": \"c!\" }, \n" \ " \"str\": \"hello, world\" } }\n" - json_tokenize(json, tokens) - json_parse_value(tokens, 0, array, 0) - print json_write_value(array[0]) + json_decode(json, array) + print json_encode(array) } function json_test_files() { + print "Testing JSON Files:" print "load: [" json_load("email.txt", mail) "]" - print "mail: " json_write_value(mail, " ") + print "mail: " json_encode(mail, " ") mail["andy753421"] = "andy753421@gmail.com" mail["andy"] = "andy@gmail.com" mail["somebody"] = "foo@example.com" - print "mail: " json_write_value(mail, " ") + print "mail: " json_encode(mail, " ") print "save: [" json_save("email.txt", mail) "]" }