Use PHP functions in JavaScript

JavaScript json_decode

Decodes the JSON representation into a PHP 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
function json_decode (str_json) {
    // Decodes the JSON representation into a PHP value  
    // 
    // version: 1008.1718
    // discuss at: http://phpjs.org/functions/json_decode    // +      original by: Public Domain (http://www.json.org/json2.js)
    // + reimplemented by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +      improved by: T.J. Leahy
    // +      improved by: Michael White
    // *        example 1: json_decode('[\n    "e",\n    {\n    "pluribus": "unum"\n}\n]');    // *        returns 1: ['e', {pluribus: 'unum'}]
    /*
        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 json = this.window.JSON;    if (typeof json === 'object' && typeof json.parse === 'function') {
        try {
            return json.parse(str_json);
        } catch(err) {
            if (!(err instanceof SyntaxError)) {                throw new Error('Unexpected error type in json_decode()');
            }
            this.php_js = this.php_js || {};
            this.php_js.last_error_json = 4; // usable by json_last_error()
            return null;        } 
    }
    
    var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
    var j;    var text = str_json;
 
    // Parsing happens in four stages. In the first stage, we replace certain
    // Unicode characters with escape sequences. JavaScript handles many characters
    // incorrectly, either silently deleting them, or treating them as line endings.    cx.lastIndex = 0;
    if (cx.test(text)) {
        text = text.replace(cx, function (a) {
            return '\\u' +
            ('0000' + a.charCodeAt(0).toString(16)).slice(-4);        });
    }
 
    // In the second stage, we run the text against regular expressions that look
    // for non-JSON patterns. We are especially concerned with '()' and 'new'    // because they can cause invocation, and '=' because it can cause mutation.
    // But just to be safe, we want to reject all unexpected forms.
 
    // We split the second stage into 4 regexp operations in order to work around
    // crippling inefficiencies in IE's and Safari's regexp engines. First we    // replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
    // replace all simple value tokens with ']' characters. Third, we delete all
    // open brackets that follow a colon or comma or that begin the text. Finally,
    // we look to see that the remaining characters are only whitespace or ']' or
    // ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.    if ((/^[\],:{}\s]*$/).
        test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').
            replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
            replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
         // In the third stage we use the eval function to compile the text into a
        // JavaScript structure. The '{' operator is subject to a syntactic ambiguity
        // in JavaScript: it can begin a block or an object literal. We wrap the text
        // in parens to eliminate the ambiguity.
         j = eval('(' + text + ')');
 
        return j;
    }
     this.php_js = this.php_js || {};
    this.php_js.last_error_json = 4; // usable by json_last_error()
    return null;
}
external links: original PHP docs | raw js source

Examples

Running

1
json_decode('[\n    "e",\n    {\n    "pluribus": "unum"\n}\n]');

Should return

1
['e', {pluribus: 'unum'}]

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_decode goodness in JavaScript.

Comments

Add Comment
Use:
[CODE]
your_stuff('here');
[/CODE]
for proper code formatting
By submitting code here you are allowing us to use it in php.js hence dual licensing it under the MIT and GPL licenses

Gravatar
Brett Zamir
26 Oct '09 Permalink

q  Have made a fix (NULL to null) and added support for json_last_error(); see commits at http://github.com/kvz/phpjs/commits/master/

Gravatar
Kevin van Zonneveld
25 Oct '09 Permalink

q  @ Michael White: Just now saw your comment on json_encode & implemented the fixes!

http://github.com/kvz/phpjs/commit/cae72555c08c11ec416f1c8ecfcd5e42509cb46d

Gravatar
Kevin van Zonneveld
25 Oct '09 Permalink

q  Yeah we need to look into this. Could be much better but I don't have enough time to work it myself right now. Maybe someone else reading this can have a go at it?
Would be much appreciated!

Gravatar
Michael White
20 Oct '09 Permalink

q  @kevin Hey - sorry. that's my fault. It should indeed return NULL if there's an error. My main point was that we should use the try/catch to prevent exceptions from causing the JS to just stop unexpectedly.

Gravatar
Brett Zamir
18 Oct '09 Permalink

q  @Michael: Thanks, but is that really how PHP handles it? the docs for json_decode say "NULL is returned if the json cannot be decoded or if the encoded data is deeper than the recursion limit." Would be nice if someone could check for all possible json.parse/json.stringify errors (and the rest of the function when these are not available) to check for the type of errors also recorded by json_last_error (and to add a property to the "this.php_js" global so that json_last_error() can retrieve this info). Ditto for json_encode().

Gravatar
Michael White
18 Oct '09 Permalink

q  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 JSON data.

try {
    return json.parse(str_json);
}
catch(err) {
    return str_json;
}

Gravatar
Kevin van Zonneveld
18 Jun '09 Permalink

q  @ T.J. Leahy + Brett Zamir: Awesome!

Gravatar
Brett Zamir
18 Jun '09 Permalink

q  Fixed in SVN. Thanks for the report!

FYI, if you reference a variable like JSON and it doesn't exist, it will cause a failure in JS, so we have to either enclose such a reference in a try-catch block (ugly) or reference it as a property of the window object--since referencing an undefined property does not give an error in JS.

As far as why I used "this.window" ("window" would be fine for most environments), it is because this will both refer to:

1) the window object in the non-namespaced version (it resolves to "window.window" which, in JS, thankfully for our needs, happens to be a recursive reference to window), and
2) the window attached to the object itself in the namespaced version (our namespaced version allows for the window to be set to a value other than the global "window" object for environments like JavaScript modules in Firefox extensions where 'window' is not available as a global but is passed in during object construction, and should automatically set it to the window global otherwise).

Gravatar
T.J. Leahy
17 Jun '09 Permalink

q  This function should check to see if the browser has native JSON decoding first (IE8, FF 3.5) and use that when available. Would make it faster and safer then running the input against multiple regular expressions. See http://hacks.mozilla.org/2009/06/security-performance-native-json/

if (typeof JSON == "object" && typeof JSON.parse == "function") {
    return JSON.parse(str_json);
}


Contribute a New function

More functions

In this category

» json_decode
json_encode
json_last_error

Support us

spread the word:


Use any PHP function in JavaScript


These kind folks have already donated: @HalfWinter, Paulo Freitas, Andros Peña Romo, Nitin Gupta, @nikosdion, Anonymous, Anonymous and Shawn Houser.
<your name here>

Click here to lend your support to: phpjs and make a donation at www.pledgie.com !