<% /* * Copyright: * (C) 2006 by Derrell Lipman * All rights reserved * * License: * LGPL 2.1: http://creativecommons.org/licenses/LGPL/2.1/ */ /* * This module provides a JSON encoder. */ /* escape a string as required by json */ function _escape(s) { var i; var arr = new Array(); for (i = 0; i < strlen(s); i++) { var c = substr(s, i, 1); if (c == '\x00') { arr[i] = '\\u0000'; } if (Json._internal.convert[c] != undefined) { arr[i] = Json._internal.convert[c]; } else { arr[i] = c; } } if (arr.length == 0) { return ""; } return join("", arr); } /* encode an arbitrary object. called recursively, for object and array */ function _encode(o) { var type = nativeTypeOf(o); if (type == "undefined") { return "null"; /* you really shouldn't count on this! */ } else if (type == "null") { return "null"; } else if (type == "boolean") { if (o) { return "true"; } else { return "false"; } } else if (type == "c_function" || type == "js_function" || type == "string_c_function") { /* no output */ } else if (type == "float" || type == "integer" || type == "integer64") { return o + 0; } else if (type == "pointer") { var x = "" + o; return '"' + substr(x, 16, strlen(x) - 16 - 1) + '"'; } else if (type == "object") { var buf; /* Is this an array or an ordinary object? */ if (o["length"] != undefined) { var i; /* Assume it's an array if there's a length field */ buf = "["; for (i = 0; i < o.length; i++) { /* * NOTE: We don't support sparse arrays nor associative * arrays. Should we later want to do either, we're supposed * to send it as an object rather than as an array. */ if (i > 0) { buf = buf + ","; } buf = buf + this.encode(o[i]); } buf = buf + "]"; } else if (o["__type"] == "_JSON_Date") { buf = "" + o.encoding(); } else { /* No length field, so it must be an ordinary object */ var key; var first = true; buf = "{"; for (key in o) { if (! first) { buf = buf + ","; } buf = buf + '"' + key + '":' + this.encode(o[key]); first = false; } buf = buf + "}"; } return buf; } else if (type == "string") { return '"' + this._internal.escape(o) + '"'; } else { return '{ "unknown_object":"' + type + '"}'; } } /* Allocate the public Json access object */ Json = new Object(); /* Json.encode(): encode an arbitrary object */ Json.encode = _encode; _encode = null; /* Json.decode(): decode a string into its object form */ Json.decode = literal_to_var; /* Internal stuff, not for external access */ Json._internal = new Object(); Json._internal.escape = _escape; _escape = null; Json._internal.convert = new Object(); Json._internal.convert['\b'] = '\\b'; Json._internal.convert['\t'] = '\\t'; Json._internal.convert['\n'] = '\\n'; Json._internal.convert['\f'] = '\\f'; Json._internal.convert['\r'] = '\\r'; Json._internal.convert['"'] = '\\"'; Json._internal.convert['\\'] = '\\\\'; Json._internal.convert['\x01'] = '\\u0001'; Json._internal.convert['\x02'] = '\\u0002'; Json._internal.convert['\x03'] = '\\u0003'; Json._internal.convert['\x04'] = '\\u0004'; Json._internal.convert['\x05'] = '\\u0005'; Json._internal.convert['\x06'] = '\\u0006'; Json._internal.convert['\x07'] = '\\u0007'; Json._internal.convert['\x08'] = '\\u0008'; Json._internal.convert['\x09'] = '\\u0009'; Json._internal.convert['\x0a'] = '\\u000a'; Json._internal.convert['\x0b'] = '\\u000b'; Json._internal.convert['\x0c'] = '\\u000c'; Json._internal.convert['\x0d'] = '\\u000d'; Json._internal.convert['\x0e'] = '\\u000e'; Json._internal.convert['\x0f'] = '\\u000f'; Json._internal.convert['\x10'] = '\\u0010'; Json._internal.convert['\x11'] = '\\u0011'; Json._internal.convert['\x12'] = '\\u0012'; Json._internal.convert['\x13'] = '\\u0013'; Json._internal.convert['\x14'] = '\\u0014'; Json._internal.convert['\x15'] = '\\u0015'; Json._internal.convert['\x16'] = '\\u0016'; Json._internal.convert['\x17'] = '\\u0017'; Json._internal.convert['\x18'] = '\\u0018'; Json._internal.convert['\x19'] = '\\u0019'; Json._internal.convert['\x1a'] = '\\u001a'; Json._internal.convert['\x1b'] = '\\u001b'; Json._internal.convert['\x1c'] = '\\u001c'; Json._internal.convert['\x1d'] = '\\u001d'; Json._internal.convert['\x1e'] = '\\u001e'; Json._internal.convert['\x1f'] = '\\u001f'; /* * At some point, we probably want to add \x80-\xff as well, and it's then * probably more efficient to generate these strings dynamically. (Even now * it may be, but this was the the way I started, and so it remains.) */ /* Test it */ /* libinclude("base.js"); function testFormat() { var test = new Object(); test.int = 23; test.str = "hello world"; test.float = 223.1; test.bool = true; test.array = new Array(); test.array[0] = "hello"; test.array[1] = "world"; test.obj = new Object(); test.obj.int = 1000; test.obj.array = new Array(); test.obj.array[0] = 42; test.obj.array[1] = 223; printf("%s\n", Json.encode(test)); } testFormat(); */ /* libinclude("base.js"); function testParse() { var s; s = '{ "x" : 23 }'; obj = Json.decode(s); printf("Decode/encode of\n\t%s\nyielded\n\t%s\n\n", s, Json.encode(obj)); s = '{ "x" : [ 23, 42] }'; obj = Json.decode(s); printf("Decode/encode of\n\t%s\nyielded\n\t%s\n\n", s, Json.encode(obj)); s = '[ 13, 19, { "x" : [ 23, 42] }, 223 ]'; obj = Json.decode(s); printf("Decode/encode of\n\t%s\nyielded\n\t%s\n\n", s, Json.encode(obj)); s = '{ "x" : [ "hi" ] }'; obj = Json.decode(s); printf("Decode/encode of\n\t%s\nyielded\n\t%s\n\n", s, Json.encode(obj)); s = '[ 13, 19, { "x" : [ 23, 42, { "y":{"a":"hello", "b":"world", "c":[1,2,3]}}] }, 223 ]'; obj = Json.decode(s); printf("Decode/encode of\n\t%s\nyielded\n\t%s\n\n", s, Json.encode(obj)); } testParse(); */ /* * Local Variables: * mode: c * End: */ %>