
if (!Object.prototype.toJsonString) {

    Array.prototype.toJsonString = function (w) {
        var a = [],     // The array holding the partial texts.
            i,          // Loop counter.
            l = this.length,
            v;          // The value to be stringified.

// For each value in this array...

        for (i = 0; i < l; i += 1) {
            v = this[i];
            switch (typeof v) {
            case 'object':

// Serialize a JavaScript object value. Ignore objects thats lack the
// toJsonString method. Due to a specification error in ECMAScript,
// typeof null is 'object', so watch out for that case.

                if (v) {
                    if (typeof v.toJsonString === 'function') {
                        a.push(v.toJsonString(w));
                    }
                } else {
                    a.push('null');
                }
                break;

            case 'string':
            case 'number':
            case 'boolean':
                a.push(v.toJsonString());

// Values without a Json representation are ignored.

            }
        }

// Join all of the member texts together and wrap them in brackets.

        return '[' + a.join(',') + ']';
    };


    Boolean.prototype.toJsonString = function () { return String(this); };


    Date.prototype.toJsonString = function () {
		return 'new Date('+this.valueOf()+')';
/*    
// Eventually, this method will be based on the date.toISOString method.

        function f(n) { return n < 10 ? '0' + n : n; }

        return '"' + this.getUTCFullYear() + '-' +
                f(this.getUTCMonth() + 1)  + '-' +
                f(this.getUTCDate())       + 'T' +
                f(this.getUTCHours())      + ':' +
                f(this.getUTCMinutes())    + ':' +
                f(this.getUTCSeconds())    + 'Z"';*/
    };


    Number.prototype.toJsonString = function () { return isFinite(this) ? String(this) : 'null'; };


    Object.prototype.toJsonString = function (w) {
        var a = [],     // The array holding the partial texts.
            k,          // The current key.
            i,          // The loop counter.
            v;          // The current value.

// If a whitelist (array of keys) is provided, use it assemble the components
// of the object.

        if (w) {
            for (i = 0; i < w.length; i += 1) {
                k = w[i];
                if (typeof k === 'string') {
                    v = this[k];
                    switch (typeof v) {
                    case 'object':

// Serialize a JavaScript object value. Ignore objects that lack the
// toJsonString method. Due to a specification error in ECMAScript,
// typeof null is 'object', so watch out for that case.

                        if (v) {
                            if (typeof v.toJsonString === 'function') {
                                a.push(k/*.toJsonString()*/ + ':' +
                                       v.toJsonString(w));
                            }
                        } else {
                            a.push(k/*.toJsonString()*/ + ':null');
                        }
                        break;

                    case 'string':
                    case 'number':
                    case 'boolean':
                        a.push(k/*.toJsonString()*/ + ':' + v.toJsonString());

// Values without a Json representation are ignored.

                    }
                }
            }
        } else {

// Iterate through all of the keys in the object, ignoring the proto chain
// and keys that are not strings.

            for (k in this) {
                if (typeof k === 'string' &&
                        Object.prototype.hasOwnProperty.apply(this, [k])) {
                    v = this[k];
                    switch (typeof v) {
                    case 'object':

// Serialize a JavaScript object value. Ignore objects that lack the
// toJsonString method. Due to a specification error in ECMAScript,
// typeof null is 'object', so watch out for that case.

                        if (v) {
                            if (typeof v.toJsonString === 'function') {
                                a.push(k/*.toJsonString()*/ + ':' +
                                       v.toJsonString());
                            }
                        } else {
                            a.push(k/*.toJsonString()*/ + ':null');
                        }
                        break;

                    case 'string':
                    case 'number':
                    case 'boolean':
                        a.push(k/*.toJsonString()*/ + ':' + v.toJsonString());

// Values without a Json representation are ignored.

                    }
                }
            }
        }

// Join all of the member texts together and wrap them in braces.

        return '{' + a.join(',') + '}';
    };


    (function () {

// We do this in an immediate anonymous function to
// avoid defining global variables.

// m is a table of character substitutions.

        var m = {
            '\b': '\\b',
            '\t': '\\t',
            '\n': '\\n',
            '\f': '\\f',
            '\r': '\\r',
            '"' : '\\"',
            '\\': '\\\\'
        };
/*
        String.prototype.parseJson = function( filter) {
            var j;

            function walk(k, v) {
                var i;
                if (v && typeof v === 'object') {
                    for (i in v) {
                        if (Object.prototype.hasOwnProperty.apply(v, [i])) {
                            v[i] = walk(i, v[i]);
                        }
                    }
                }
                return filter(k, v);
            }


// Parsing happens in three stages. In the first stage, we run the text against
// a regular expression which looks for non-Json characters. We are especially
// concerned with '()' and 'new' because they can cause invocation, and '='
// because it can cause mutation. But just to be safe, we will reject all
// unexpected characters.

// We split the first stage into 3 regexp operations in order to work around
// crippling deficiencies in Safari's regexp engine. First we replace all
// backslash pairs with '@' (a non-Json character). Second we delete all of
// the string literals. Third, we look to see if only Json characters
// remain. If so, then the text is safe for eval.

            if (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/.test(this.
                    replace(/\\./g, '@').
                    replace(/"[^"\\\n\r]*"/g, ''))) {

// In the second 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('(' + this + ')');

// In the optional third stage, we recursively walk the new structure, passing
// each name/value pair to a filter function for possible transformation.

				return typeof filter === 'function' ? walk('', j) : j;
			}

// If the text is not Json parseable, then a SyntaxError is thrown.

            throw new SyntaxError('parseJson');
        };
        */

		String.parseJson = function( json, type ) {
		//	if (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/.test(json.
		//			replace(/\\./g, '@').
		//			replace(/"[^"\\\n\r]*"/g, ''))) {

				var o = eval('(' + json + ')');
				if( !type ) return o;				
				if( !o ) return null;
				if( o instanceof Array )
					return [].fromRawObject(o,type);							
				return (new type()).fromRawObject(o);
		//	}
		//	throw new SyntaxError('parseJson');
		}

        String.prototype.toJsonString = function () {

// If the string contains no control characters, no quote characters, and no
// backslash characters, then we can simply slap some quotes around it.
// Otherwise we must also replace the offending characters with safe
// sequences.

            if (/["\\\x00-\x1f]/.test(this)) {
                return '"' + this.replace(/[\x00-\x1f\\"]/g, function (a) {
                    var c = m[a];
                    if (c) {
                        return c;
                    }
                    c = a.charCodeAt();
                    return '\\u00' +
                        Math.floor(c / 16).toString(16) +
                        (c % 16).toString(16);
                }) + '"';
            }
            return '"' + this + '"';
        };
    })();
    
	Object.prototype.fromRawObject = function( o )
	{
		for( var p in o )
			if( this.hasOwnProperty(p) )
			{
				if( o[p] == null ) { this[p] = null; continue; }
				if( o[p] instanceof Array )
				{
					var t = this.getClassOf(p);
					if( !t ) this[p] = o[p];
					else
					{
						this[p] = [];
						this[p].fromRawObject(o[p],t);
					}
					continue;
				}
				if( this[p] == null )
				{
					var t = this.getClassOf(p);
					if( t ) this[p] = new t();
					else { this[p] = o[p]; continue; }
				}
						
				switch( typeof this[p] )
				{
					case 'function': break;
					case 'object': this[p] = this[p].fromRawObject(o[p]); break;
					case 'string':
					case 'number':
					case 'boolean': this[p] = o[p]; break;
				}
			}
		return this;
	}
	Object.prototype.getClassOf = function(p)
	{
		var o = this[p] ? this[p] : (new this.constructor())[p];
		if( o == null || o instanceof Array ) return null; 
		return o.constructor;
	}
	Array.prototype.fromRawObject = function( a, t )
	{
		this.splice(0,this.length);
		if( t ) {
			for( var i = 0; i < a.length; ++i )
				this.push( (new t()).fromRawObject( a[i] ) );
		}
		else {
			for( var i = 0; i < a.length; ++i )
				this.push( a[i] );
		}
		return this;
	}
	String.prototype.fromRawObject = function(o) { return o; }
	Number.prototype.fromRawObject = function(o) { return o; }
	Boolean.prototype.fromRawObject = function(o) { return o; }
	Date.prototype.fromRawObject = function(o)
	{
		if(o instanceof Date) return o;
		return o ? Date.parseUTCExact(o,"yyyy-MM-ddTHH:mm:ssZ") : null;
	}
}