JavaScript json_encode
Returns the JSON representation of a value
1 2 3 4 56 7 8 9 1011 12 13 14 1516 17 18 19 2021 22 23 24 2526 27 28 29 3031 32 33 34 3536 37 38 39 4041 42 43 44 4546 47 48 49 5051 52 53 54 5556 57 58 59 6061 62 63 64 6566 67 68 69 7071 72 73 74 7576 77 78 79 8081 82 83 84 8586 87 88 89 9091 92 93 94 9596 97 98 99 100101 102 103 104 105106 107 108 109 110111 112 113 114 115116 117 118 119 120121 122 123 124 125126 127 128 129 130131 132 133 134 135136 137 138 139 140141 142 143 144 145146 147 148 149 150151 152 153 154 155156 157 158 159 160161 162 163 164 165166 | function json_encode (mixed_val) { // Returns the JSON representation of a value // // version: 1008.1718 // discuss at: http://phpjs.org/functions/json_encode // + original by: Public Domain (http://www.json.org/json2.js) // + reimplemented by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // + improved by: Michael White // + input by: felix // + bugfixed by: Brett Zamir (http://brett-zamir.me) // * example 1: json_encode(['e', {pluribus: 'unum'}]); // * returns 1: '[\n "e",\n {\n "pluribus": "unum"\n}\n]' /* http://www.JSON.org/json2.js 2008-11-19 Public Domain. NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. See http://www.JSON.org/js.html */ var retVal, json = this.window.JSON; try { if (typeof json === 'object' && typeof json.stringify === 'function') { retVal = json.stringify(mixed_val); // Errors will not be caught here if our own equivalent to resource // (an instance of PHPJS_Resource) is used if (retVal === undefined) { throw new SyntaxError('json_encode'); } return retVal; } var value = mixed_val; var quote = function (string) { var escapable = /[\\\"\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g; var meta = { // table of character substitutions '\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '"' : '\\"', '\\': '\\\\' }; escapable.lastIndex = 0; return escapable.test(string) ? '"' + string.replace(escapable, function (a) { var c = meta[a]; return typeof c === 'string' ? c : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); }) + '"' : '"' + string + '"'; }; var str = function (key, holder) { var gap = ''; var indent = ' '; var i = 0; // The loop counter. var k = ''; // The member key. var v = ''; // The member value. var length = 0; var mind = gap; var partial = []; var value = holder[key]; // If the value has a toJSON method, call it to obtain a replacement value. if (value && typeof value === 'object' && typeof value.toJSON === 'function') { value = value.toJSON(key); } // What happens next depends on the value's type. switch (typeof value) { case 'string': return quote(value); case 'number': // JSON numbers must be finite. Encode non-finite numbers as null. return isFinite(value) ? String(value) : 'null'; case 'boolean': case 'null': // If the value is a boolean or null, convert it to a string. Note: // typeof null does not produce 'null'. The case is included here in // the remote chance that this gets fixed someday. return String(value); case 'object': // If the type is 'object', we might be dealing with an object or an array or // null. // Due to a specification blunder in ECMAScript, typeof null is 'object', // so watch out for that case. if (!value) { return 'null'; } if ((this.PHPJS_Resource && value instanceof this.PHPJS_Resource) || (window.PHPJS_Resource && value instanceof window.PHPJS_Resource)) { throw new SyntaxError('json_encode'); } // Make an array to hold the partial results of stringifying this object value. gap += indent; partial = []; // Is the value an array? if (Object.prototype.toString.apply(value) === '[object Array]') { // The value is an array. Stringify every element. Use null as a placeholder // for non-JSON values. length = value.length; for (i = 0; i < length; i += 1) { partial[i] = str(i, value) || 'null'; } // Join all of the elements together, separated with commas, and wrap them in // brackets. v = partial.length === 0 ? '[]' : gap ? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' : '[' + partial.join(',') + ']'; gap = mind; return v; } // Iterate through all of the keys in the object. for (k in value) { if (Object.hasOwnProperty.call(value, k)) { v = str(k, value); if (v) { partial.push(quote(k) + (gap ? ': ' : ':') + v); } } } // Join all of the member texts together, separated with commas, // and wrap them in braces. v = partial.length === 0 ? '{}' : gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' : '{' + partial.join(',') + '}'; gap = mind; return v; case 'undefined': // Fall-through case 'function': // Fall-through default: throw new SyntaxError('json_encode'); } }; // Make a fake root object containing our value under the key of ''. // Return the result of stringifying the value. return str('', { '': value }); } catch(err) { // Todo: ensure error handling above throws a SyntaxError in all cases where it could // (i.e., when the JSON global is not available and there is an error) if (!(err instanceof SyntaxError)) { throw new Error('Unexpected error type in json_encode()'); } this.php_js = this.php_js || {}; this.php_js.last_error_json = 4; // usable by json_last_error() return null; }} |
Examples
Running
1 | json_encode(['e', {pluribus: 'unum'}]); |
Should return
1 | '[\n "e",\n {\n "pluribus": "unum"\n}\n]' |
Dependencies
No dependencies, you can use this function standalone.
Open syntax issues
php.js uses JsLint to help us keep our code consistent and prevent some common bugs.
Eventually we want all code to pass or at least take into consideration most fixes suggested by JsLint, following this JsLint configuration we’ve decided on.
Authors
Thanks to the following developers, you get to have json_encode goodness in JavaScript.
Hi
as already listed above, PHPJS_Resource is not defined. This triggers an unexpected error for me at least if I try to use this function standalone (FF 3.5.9).
How about changing lines ## 95-97 to:
if (PHPJS_Resource && value instanceof PHPJS_Resource) {
throw new SyntaxError('json_encode');
}
?
Have made a fix (NULL to null) and added support for json_last_error(); see commits at http://github.com/kvz/phpjs/commits/master/
@ Michael White: Ok great that you did the research on this Michael!
I've implemented your fixes:
http://github.com/kvz/phpjs/commit/cae72555c08c11ec416f1c8ecfcd5e42509cb46d
@kevin I didn't know what it returned because last time I ran into this in PHP I was encountering an infinite loop because of it (long story). However, I tested it in a simple script just now and I'm getting NULL output. It also throws a PHP error warning that the type is unsupported. This happens if a resource is present anywhere in the data to be encoded.
@Michael: If you try it with a resource object, what does it return in PHP? See also my comment in json_decode().
The part that uses native browser JSON objects should be contained in a try/catch block and return the proper value in accordance with how PHP handles bad input. (The only bad input in PHP seems to be resource objects). Should we return "null" or an empty string or false here upon error?
try {
return json.stringify(mixed_val);
}
catch(err) {
return mixed_val;
}
@T. J. Leahy: Fixed in SVN. Thanks for the report! See also my note at http://phpjs.org/functions/json_decode:456#comment_64602
This function should check to see if the browser has native JSON encoding first (IE8, FF 3.5) and use that when available. Would make it faster and safer then running the object against multiple regular expressions. See http://hacks.mozilla.org/2009/06/security-performance-native-json/
if (typeof JSON == "object" && typeof JSON.stringify == "function") {
return JSON.stringify(str_json);
}


Brett Zamir
Apr 20th
e.g., these are ok:
if (window.someVar) {}
if (this.someVar) {}
but this is not:
if (someVar) {}