I realize this post is coming at the end of the day on friday, but
hopefully it will get a look =)

Going through the different JSON parsing implementations available for
GWT out there, almost all of them rely on a straight eval and note
that they should only be used for trusted code. The old JSONValue code
seems kind of quaint in light of JavaScriptObjects, and looking
through the trunk it looks like there's just a TODO in JsonUtils for
safe parsing.

Anyway, I don't have that much experience writing JSNI code, so I
wanted to run this small class past you all and see if this aligns
with GWT best practices, if I'm doing anything monumentally stupid, or
if I'm just plain missing something.

The following is a pretty basic adaptation of Douglas Crockford's
json2.js. When parse() is called, it checks to see if there is a
native JSON defined (which exists in the latest IE, Firefox, Chrome
and Safari) and simply uses that. If not, it defines a $wnd.JSON.parse
in javascript using the json2 code, which is then indistinguishable
from the native functionality in future calls (this tactic comes
straight from json2.js).

It lazily initializes the JSON object, as defining an entry point
doesn't seem like a big win, and adds a lot of support necessary to
make it happen. It also defines it on the $wnd object...scope still
occasionally confuses me in javascript, but it seemed to make more
sense to define it there than on window.

Any thoughts? Even drive by comments are useful if it gives me enough
to google. Thanks!

The code:
/**
 * Evaluates a JSON string safely
 *
 * @param <T> The type of JavaScriptObject that should be returned
 * @param jsonString The source JSON text
 * @return The evaluated object
 * @throws NullPointerException if <code>jsonString</code> is
<code>null</code>
 * @throws IllegalArgumentException if <code>jsonString</code> is
empty
 * @throws JavaScriptException if <code>jsonString</code> is non-
parseable
 */
public static  final <T extends JavaScriptObject> T  parse(String
jsonString) {
        if (jsonString == null) {
                throw new NullPointerException();
        }

        if (jsonString.length() == 0) {
                throw new IllegalArgumentException("empty argument");
        }

        // check if JSON variable is defined, if not, call init code
        if (isJsonUndefined()) {
                defineJSON();
        }

        return nativeParse(jsonString);
}

private static native <T extends JavaScriptObject> T nativeParse
(String jsonString) /*-{
        return $wnd.JSON.parse(jsonString);
}-*/;

/**
 * simple check to see if JSON object is defined
 * will be defined in browsers with native implementation
 * otherwise, will need to init manually
 *
 * @return true if JSON object is undefined
 */
protected static final native boolean isJsonUndefined() /*-{
        return !$wnd.JSON;
}-*/;

/**
 * naive way to define the JSON object *if* not already
 * natively defined by browser. straight copy from json2.js.
 */
private static final native void defineJSON() /*-{
        //http://www.JSON.org/json2.js
        //2009-09-29
        //Public Domain.
        //NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
        //See http://www.JSON.org/js.html

        // Create a JSON object only if one does not already exist.
        if (!$wnd.JSON) {
                $wnd.JSON = {};
        }

        (function () {
                var cx = 
/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f
\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;

                // create parse method if one does not exist
                // The parse method takes a text and returns
                // a JavaScript value if the text is a valid JSON text.
                if (typeof $wnd.JSON.parse !== 'function') {
                        $wnd.JSON.parse = function (text) {

                        var j;

                        // first stage, escape sequences
                        cx.lastIndex = 0;
                        if (cx.test(text)) {
                        text = text.replace(cx, function (a) {
                                return '\\u' +
                                                        ('0000' + 
a.charCodeAt(0).toString(16)).slice(-4);
                                });
                        }

                        // second stage, remove non-JSON patterns
                        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, ''))) {

                                // third stage, eval
                                j = eval('(' + text + ')');

                                return j;

                        }

                        // If the text is not JSON parseable, then a 
SyntaxError is thrown.
                        throw new SyntaxError('JSON.parse');
                };
            }
        }());

}-*/;

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Google Web Toolkit" group.
To post to this group, send email to google-web-toolkit@googlegroups.com
To unsubscribe from this group, send email to 
google-web-toolkit+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/google-web-toolkit?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to