This commit is contained in:
Douglas Crockford 2016-05-10 13:20:28 -07:00
parent ff3f6415b2
commit 107fc93c94
3 changed files with 405 additions and 403 deletions

190
json2.js
View file

@ -23,7 +23,7 @@
// of nested structures. If it is omitted, the text will
// be packed without extra whitespace. If it is a number,
// it will specify the number of spaces to indent at each
// level. If it is a string (such as '\t' or ' '),
// level. If it is a string (such as "\t" or " "),
// it contains the characters used to indent at each level.
// This method produces a JSON text from a JavaScript value.
// When an object value is found, if the object contains a toJSON
@ -39,16 +39,16 @@
// Date.prototype.toJSON = function (key) {
// function f(n) {
// // Format integers to have at least two digits.
// return n < 10
// ? '0' + 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';
// return this.getUTCFullYear() + "-" +
// f(this.getUTCMonth() + 1) + "-" +
// f(this.getUTCDate()) + "T" +
// f(this.getUTCHours()) + ":" +
// f(this.getUTCMinutes()) + ":" +
// f(this.getUTCSeconds()) + "Z";
// };
// You can provide an optional replacer method. It will be passed the
@ -79,15 +79,15 @@
// Example:
// text = JSON.stringify(['e', {pluribus: 'unum'}]);
// text = JSON.stringify(["e", {pluribus: "unum"}]);
// // text is '["e",{"pluribus":"unum"}]'
// text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
// text = JSON.stringify(["e", {pluribus: "unum"}], null, "\t");
// // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
// text = JSON.stringify([new Date()], function (key, value) {
// return this[key] instanceof Date
// ? 'Date(' + this[key] + ')'
// ? "Date(" + this[key] + ")"
// : value;
// });
// // text is '["Date(---current time---)"]'
@ -109,7 +109,7 @@
// myData = JSON.parse(text, function (key, value) {
// var a;
// if (typeof value === 'string') {
// if (typeof value === "string") {
// a =
// /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
// if (a) {
@ -122,9 +122,9 @@
// myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
// var d;
// if (typeof value === 'string' &&
// value.slice(0, 5) === 'Date(' &&
// value.slice(-1) === ')') {
// if (typeof value === "string" &&
// value.slice(0, 5) === "Date(" &&
// value.slice(-1) === ")") {
// d = new Date(value.slice(5, -1));
// if (d) {
// return d;
@ -151,12 +151,12 @@
// Create a JSON object only if one does not already exist. We create the
// methods in a closure to avoid creating global variables.
if (typeof JSON !== 'object') {
if (typeof JSON !== "object") {
JSON = {};
}
(function () {
'use strict';
"use strict";
var rx_one = /^[\],:{}\s]*$/;
var rx_two = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g;
@ -168,7 +168,7 @@ if (typeof JSON !== 'object') {
function f(n) {
// Format integers to have at least two digits.
return n < 10
? '0' + n
? "0" + n
: n;
}
@ -176,17 +176,17 @@ if (typeof JSON !== 'object') {
return this.valueOf();
}
if (typeof Date.prototype.toJSON !== 'function') {
if (typeof Date.prototype.toJSON !== "function") {
Date.prototype.toJSON = function () {
return isFinite(this.valueOf())
? this.getUTCFullYear() + '-' +
f(this.getUTCMonth() + 1) + '-' +
f(this.getUTCDate()) + 'T' +
f(this.getUTCHours()) + ':' +
f(this.getUTCMinutes()) + ':' +
f(this.getUTCSeconds()) + 'Z'
? this.getUTCFullYear() + "-" +
f(this.getUTCMonth() + 1) + "-" +
f(this.getUTCDate()) + "T" +
f(this.getUTCHours()) + ":" +
f(this.getUTCMinutes()) + ":" +
f(this.getUTCSeconds()) + "Z"
: null;
};
@ -210,13 +210,13 @@ if (typeof JSON !== 'object') {
rx_escapable.lastIndex = 0;
return rx_escapable.test(string)
? '"' + string.replace(rx_escapable, function (a) {
? "\"" + string.replace(rx_escapable, function (a) {
var c = meta[a];
return typeof c === 'string'
return typeof c === "string"
? c
: '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
}) + '"'
: '"' + string + '"';
: "\\u" + ("0000" + a.charCodeAt(0).toString(16)).slice(-4);
}) + "\""
: "\"" + string + "\"";
}
@ -234,51 +234,51 @@ if (typeof JSON !== 'object') {
// If the value has a toJSON method, call it to obtain a replacement value.
if (value && typeof value === 'object' &&
typeof value.toJSON === 'function') {
if (value && typeof value === "object" &&
typeof value.toJSON === "function") {
value = value.toJSON(key);
}
// If we were called with a replacer function, then call the replacer to
// obtain a replacement value.
if (typeof rep === 'function') {
if (typeof rep === "function") {
value = rep.call(holder, key, value);
}
// What happens next depends on the value's type.
switch (typeof value) {
case 'string':
case "string":
return quote(value);
case 'number':
case "number":
// JSON numbers must be finite. Encode non-finite numbers as null.
return isFinite(value)
? String(value)
: 'null';
: "null";
case 'boolean':
case '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
// typeof null does not produce "null". The case is included here in
// the remote chance that this gets fixed someday.
return String(value);
// If the type is 'object', we might be dealing with an object or an array or
// If the type is "object", we might be dealing with an object or an array or
// null.
case 'object':
case "object":
// Due to a specification blunder in ECMAScript, typeof null is 'object',
// Due to a specification blunder in ECMAScript, typeof null is "object",
// so watch out for that case.
if (!value) {
return 'null';
return "null";
}
// Make an array to hold the partial results of stringifying this object value.
@ -288,41 +288,41 @@ if (typeof JSON !== 'object') {
// Is the value an array?
if (Object.prototype.toString.apply(value) === '[object 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';
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(',') + ']';
? "[\n" + gap + partial.join(",\n" + gap) + "\n" + mind + "]"
: "[" + partial.join(",") + "]";
gap = mind;
return v;
}
// If the replacer is an array, use it to select the members to be stringified.
if (rep && typeof rep === 'object') {
if (rep && typeof rep === "object") {
length = rep.length;
for (i = 0; i < length; i += 1) {
if (typeof rep[i] === 'string') {
if (typeof rep[i] === "string") {
k = rep[i];
v = str(k, value);
if (v) {
partial.push(quote(k) + (
gap
? ': '
: ':'
? ": "
: ":"
) + v);
}
}
@ -337,8 +337,8 @@ if (typeof JSON !== 'object') {
if (v) {
partial.push(quote(k) + (
gap
? ': '
: ':'
? ": "
: ":"
) + v);
}
}
@ -349,10 +349,10 @@ if (typeof JSON !== 'object') {
// and wrap them in braces.
v = partial.length === 0
? '{}'
? "{}"
: gap
? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}'
: '{' + partial.join(',') + '}';
? "{\n" + gap + partial.join(",\n" + gap) + "\n" + mind + "}"
: "{" + partial.join(",") + "}";
gap = mind;
return v;
}
@ -360,15 +360,15 @@ if (typeof JSON !== 'object') {
// If the JSON object does not yet have a stringify method, give it one.
if (typeof JSON.stringify !== 'function') {
if (typeof JSON.stringify !== "function") {
meta = { // table of character substitutions
'\b': '\\b',
'\t': '\\t',
'\n': '\\n',
'\f': '\\f',
'\r': '\\r',
'"': '\\"',
'\\': '\\\\'
"\b": "\\b",
"\t": "\\t",
"\n": "\\n",
"\f": "\\f",
"\r": "\\r",
"\"": "\\\"",
"\\": "\\\\"
};
JSON.stringify = function (value, replacer, space) {
@ -379,20 +379,20 @@ if (typeof JSON !== 'object') {
// produce text that is more easily readable.
var i;
gap = '';
indent = '';
gap = "";
indent = "";
// If the space parameter is a number, make an indent string containing that
// many spaces.
if (typeof space === 'number') {
if (typeof space === "number") {
for (i = 0; i < space; i += 1) {
indent += ' ';
indent += " ";
}
// If the space parameter is a string, it will be used as the indent string.
} else if (typeof space === 'string') {
} else if (typeof space === "string") {
indent = space;
}
@ -400,23 +400,23 @@ if (typeof JSON !== 'object') {
// Otherwise, throw an error.
rep = replacer;
if (replacer && typeof replacer !== 'function' &&
(typeof replacer !== 'object' ||
typeof replacer.length !== 'number')) {
throw new Error('JSON.stringify');
if (replacer && typeof replacer !== "function" &&
(typeof replacer !== "object" ||
typeof replacer.length !== "number")) {
throw new Error("JSON.stringify");
}
// Make a fake root object containing our value under the key of ''.
// Make a fake root object containing our value under the key of "".
// Return the result of stringifying the value.
return str('', {'': value});
return str("", {"": value});
};
}
// If the JSON object does not yet have a parse method, give it one.
if (typeof JSON.parse !== 'function') {
if (typeof JSON.parse !== "function") {
JSON.parse = function (text, reviver) {
// The parse method takes a text and an optional reviver function, and returns
@ -432,7 +432,7 @@ if (typeof JSON !== 'object') {
var k;
var v;
var value = holder[key];
if (value && typeof value === 'object') {
if (value && typeof value === "object") {
for (k in value) {
if (Object.prototype.hasOwnProperty.call(value, k)) {
v = walk(value, k);
@ -456,51 +456,51 @@ if (typeof JSON !== 'object') {
rx_dangerous.lastIndex = 0;
if (rx_dangerous.test(text)) {
text = text.replace(rx_dangerous, function (a) {
return '\\u' +
('0000' + a.charCodeAt(0).toString(16)).slice(-4);
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.
// 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
// 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.
// 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 (
rx_one.test(
text
.replace(rx_two, '@')
.replace(rx_three, ']')
.replace(rx_four, '')
.replace(rx_two, "@")
.replace(rx_three, "]")
.replace(rx_four, "")
)
) {
// 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
// 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 + ')');
j = eval("(" + text + ")");
// In the optional fourth stage, we recursively walk the new structure, passing
// each name/value pair to a reviver function for possible transformation.
return typeof reviver === 'function'
? walk({'': j}, '')
return (typeof reviver === "function")
? walk({"": j}, "")
: j;
}
// If the text is not JSON parseable, then a SyntaxError is thrown.
throw new SyntaxError('JSON.parse');
throw new SyntaxError("JSON.parse");
};
}
}());

View file

@ -1,6 +1,6 @@
/*
json_parse.js
2015-05-02
2016-05-02
Public Domain.
@ -25,7 +25,7 @@
myData = json_parse(text, function (key, value) {
var a;
if (typeof value === 'string') {
if (typeof value === "string") {
a =
/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
if (a) {
@ -67,14 +67,14 @@ var json_parse = (function () {
var at; // The index of the current character
var ch; // The current character
var escapee = {
'"': '"',
'\\': '\\',
'/': '/',
b: '\b',
f: '\f',
n: '\n',
r: '\r',
t: '\t'
"\"": "\"",
"\\": "\\",
"/": "/",
b: "\b",
f: "\f",
n: "\n",
r: "\r",
t: "\t"
};
var text;
@ -83,7 +83,7 @@ var json_parse = (function () {
// Call error when something is wrong.
throw {
name: 'SyntaxError',
name: "SyntaxError",
message: m,
at: at,
text: text
@ -110,40 +110,40 @@ var json_parse = (function () {
// Parse a number value.
var number;
var string = '';
var value;
var string = "";
if (ch === '-') {
string = '-';
next('-');
if (ch === "-") {
string = "-";
next("-");
}
while (ch >= '0' && ch <= '9') {
while (ch >= "0" && ch <= "9") {
string += ch;
next();
}
if (ch === '.') {
string += '.';
while (next() && ch >= '0' && ch <= '9') {
if (ch === ".") {
string += ".";
while (next() && ch >= "0" && ch <= "9") {
string += ch;
}
}
if (ch === 'e' || ch === 'E') {
if (ch === "e" || ch === "E") {
string += ch;
next();
if (ch === '-' || ch === '+') {
if (ch === "-" || ch === "+") {
string += ch;
next();
}
while (ch >= '0' && ch <= '9') {
while (ch >= "0" && ch <= "9") {
string += ch;
next();
}
}
number = +string;
if (!isFinite(number)) {
value = +string;
if (!isFinite(value)) {
error("Bad number");
} else {
return number;
return value;
}
};
@ -153,20 +153,20 @@ var json_parse = (function () {
var hex;
var i;
var string = '';
var value = "";
var uffff;
// When parsing for string values, we must look for " and \ characters.
if (ch === '"') {
if (ch === "\"") {
while (next()) {
if (ch === '"') {
if (ch === "\"") {
next();
return string;
return value;
}
if (ch === '\\') {
if (ch === "\\") {
next();
if (ch === 'u') {
if (ch === "u") {
uffff = 0;
for (i = 0; i < 4; i += 1) {
hex = parseInt(next(), 16);
@ -175,14 +175,14 @@ var json_parse = (function () {
}
uffff = uffff * 16 + hex;
}
string += String.fromCharCode(uffff);
} else if (typeof escapee[ch] === 'string') {
string += escapee[ch];
value += String.fromCharCode(uffff);
} else if (typeof escapee[ch] === "string") {
value += escapee[ch];
} else {
break;
}
} else {
string += ch;
value += ch;
}
}
}
@ -193,7 +193,7 @@ var json_parse = (function () {
// Skip whitespace.
while (ch && ch <= ' ') {
while (ch && ch <= " ") {
next();
}
};
@ -203,24 +203,24 @@ var json_parse = (function () {
// true, false, or null.
switch (ch) {
case 't':
next('t');
next('r');
next('u');
next('e');
case "t":
next("t");
next("r");
next("u");
next("e");
return true;
case 'f':
next('f');
next('a');
next('l');
next('s');
next('e');
case "f":
next("f");
next("a");
next("l");
next("s");
next("e");
return false;
case 'n':
next('n');
next('u');
next('l');
next('l');
case "n":
next("n");
next("u");
next("l");
next("l");
return null;
}
error("Unexpected '" + ch + "'");
@ -232,23 +232,23 @@ var json_parse = (function () {
// Parse an array value.
var array = [];
var arr = [];
if (ch === '[') {
next('[');
if (ch === "[") {
next("[");
white();
if (ch === ']') {
next(']');
return array; // empty array
if (ch === "]") {
next("]");
return arr; // empty array
}
while (ch) {
array.push(value());
arr.push(value());
white();
if (ch === ']') {
next(']');
return array;
if (ch === "]") {
next("]");
return arr;
}
next(',');
next(",");
white();
}
}
@ -260,29 +260,29 @@ var json_parse = (function () {
// Parse an object value.
var key;
var object = {};
var obj = {};
if (ch === '{') {
next('{');
if (ch === "{") {
next("{");
white();
if (ch === '}') {
next('}');
return object; // empty object
if (ch === "}") {
next("}");
return obj; // empty object
}
while (ch) {
key = string();
white();
next(':');
if (Object.hasOwnProperty.call(object, key)) {
error('Duplicate key "' + key + '"');
next(":");
if (Object.hasOwnProperty.call(obj, key)) {
error("Duplicate key '" + key + "'");
}
object[key] = value();
obj[key] = value();
white();
if (ch === '}') {
next('}');
return object;
if (ch === "}") {
next("}");
return obj;
}
next(',');
next(",");
white();
}
}
@ -296,16 +296,16 @@ var json_parse = (function () {
white();
switch (ch) {
case '{':
case "{":
return object();
case '[':
case "[":
return array();
case '"':
case "\"":
return string();
case '-':
case "-":
return number();
default:
return (ch >= '0' && ch <= '9')
return (ch >= "0" && ch <= "9")
? number()
: word();
}
@ -319,7 +319,7 @@ var json_parse = (function () {
text = source;
at = 0;
ch = ' ';
ch = " ";
result = value();
white();
if (ch) {
@ -332,25 +332,25 @@ var json_parse = (function () {
// in an empty key. If there is not a reviver function, we simply return the
// result.
return (typeof reviver === 'function')
return (typeof reviver === "function")
? (function walk(holder, key) {
var k;
var v;
var value = holder[key];
if (value && typeof value === 'object') {
for (k in value) {
if (Object.prototype.hasOwnProperty.call(value, k)) {
v = walk(value, k);
var val = holder[key];
if (val && typeof val === "object") {
for (k in val) {
if (Object.prototype.hasOwnProperty.call(val, k)) {
v = walk(val, k);
if (v !== undefined) {
value[k] = v;
val[k] = v;
} else {
delete value[k];
delete val[k];
}
}
}
}
return reviver.call(holder, key, value);
}({'': result}, ''))
return reviver.call(holder, key, val);
}({"": result}, ""))
: result;
};
}());

View file

@ -1,6 +1,6 @@
/*
json_parse_state.js
2015-05-02
2016-05-02
Public Domain.
@ -25,7 +25,7 @@
myData = json_parse(text, function (key, value) {
var a;
if (typeof value === 'string') {
if (typeof value === "string") {
a =
/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
if (a) {
@ -61,7 +61,7 @@ var json_parse = (function () {
// This function creates a JSON parse function that uses a state machine rather
// than the dangerous eval function to parse a JSON text.
var state, // The state of the parser, one of
var state; // The state of the parser, one of
// 'go' The starting state
// 'ok' The final, accepting state
// 'firstokey' Ready for the first key of the object or
@ -74,214 +74,214 @@ var json_parse = (function () {
// an empty array
// 'avalue' Ready for the next value of an array
// 'acomma' Ready for a comma or closing ]
stack, // The stack, for controlling nesting.
container, // The current container object or array
key, // The current key
value, // The current value
escapes = { // Escapement translation table
'\\': '\\',
'"': '"',
'/': '/',
't': '\t',
'n': '\n',
'r': '\r',
'f': '\f',
'b': '\b'
var stack; // The stack, for controlling nesting.
var container; // The current container object or array
var key; // The current key
var value; // The current value
var escapes = { // Escapement translation table
"\\": "\\",
"\"": "\"",
"/": "/",
"t": "\t",
"n": "\n",
"r": "\r",
"f": "\f",
"b": "\b"
};
var string = { // The actions for string tokens
go: function () {
state = "ok";
},
string = { // The actions for string tokens
go: function () {
state = 'ok';
},
firstokey: function () {
key = value;
state = 'colon';
},
okey: function () {
key = value;
state = 'colon';
},
ovalue: function () {
state = 'ocomma';
},
firstavalue: function () {
state = 'acomma';
},
avalue: function () {
state = 'acomma';
}
firstokey: function () {
key = value;
state = "colon";
},
number = { // The actions for number tokens
go: function () {
state = 'ok';
},
ovalue: function () {
state = 'ocomma';
},
firstavalue: function () {
state = 'acomma';
},
avalue: function () {
state = 'acomma';
}
okey: function () {
key = value;
state = "colon";
},
action = {
ovalue: function () {
state = "ocomma";
},
firstavalue: function () {
state = "acomma";
},
avalue: function () {
state = "acomma";
}
};
var number = { // The actions for number tokens
go: function () {
state = "ok";
},
ovalue: function () {
state = "ocomma";
},
firstavalue: function () {
state = "acomma";
},
avalue: function () {
state = "acomma";
}
};
var action = {
// The action table describes the behavior of the machine. It contains an
// object for each token. Each object contains a method that is called when
// a token is matched in a state. An object will lack a method for illegal
// states.
'{': {
go: function () {
stack.push({state: 'ok'});
container = {};
state = 'firstokey';
},
ovalue: function () {
stack.push({container: container, state: 'ocomma', key: key});
container = {};
state = 'firstokey';
},
firstavalue: function () {
stack.push({container: container, state: 'acomma'});
container = {};
state = 'firstokey';
},
avalue: function () {
stack.push({container: container, state: 'acomma'});
container = {};
state = 'firstokey';
}
"{": {
go: function () {
stack.push({state: "ok"});
container = {};
state = "firstokey";
},
'}': {
firstokey: function () {
var pop = stack.pop();
value = container;
container = pop.container;
key = pop.key;
state = pop.state;
},
ocomma: function () {
var pop = stack.pop();
container[key] = value;
value = container;
container = pop.container;
key = pop.key;
state = pop.state;
}
ovalue: function () {
stack.push({container: container, state: "ocomma", key: key});
container = {};
state = "firstokey";
},
'[': {
go: function () {
stack.push({state: 'ok'});
container = [];
state = 'firstavalue';
},
ovalue: function () {
stack.push({container: container, state: 'ocomma', key: key});
container = [];
state = 'firstavalue';
},
firstavalue: function () {
stack.push({container: container, state: 'acomma'});
container = [];
state = 'firstavalue';
},
avalue: function () {
stack.push({container: container, state: 'acomma'});
container = [];
state = 'firstavalue';
}
firstavalue: function () {
stack.push({container: container, state: "acomma"});
container = {};
state = "firstokey";
},
']': {
firstavalue: function () {
var pop = stack.pop();
value = container;
container = pop.container;
key = pop.key;
state = pop.state;
},
acomma: function () {
var pop = stack.pop();
container.push(value);
value = container;
container = pop.container;
key = pop.key;
state = pop.state;
}
},
':': {
colon: function () {
if (Object.hasOwnProperty.call(container, key)) {
throw new SyntaxError('Duplicate key "' + key + '"');
}
state = 'ovalue';
}
},
',': {
ocomma: function () {
container[key] = value;
state = 'okey';
},
acomma: function () {
container.push(value);
state = 'avalue';
}
},
'true': {
go: function () {
value = true;
state = 'ok';
},
ovalue: function () {
value = true;
state = 'ocomma';
},
firstavalue: function () {
value = true;
state = 'acomma';
},
avalue: function () {
value = true;
state = 'acomma';
}
},
'false': {
go: function () {
value = false;
state = 'ok';
},
ovalue: function () {
value = false;
state = 'ocomma';
},
firstavalue: function () {
value = false;
state = 'acomma';
},
avalue: function () {
value = false;
state = 'acomma';
}
},
'null': {
go: function () {
value = null;
state = 'ok';
},
ovalue: function () {
value = null;
state = 'ocomma';
},
firstavalue: function () {
value = null;
state = 'acomma';
},
avalue: function () {
value = null;
state = 'acomma';
}
avalue: function () {
stack.push({container: container, state: "acomma"});
container = {};
state = "firstokey";
}
};
},
"}": {
firstokey: function () {
var pop = stack.pop();
value = container;
container = pop.container;
key = pop.key;
state = pop.state;
},
ocomma: function () {
var pop = stack.pop();
container[key] = value;
value = container;
container = pop.container;
key = pop.key;
state = pop.state;
}
},
"[": {
go: function () {
stack.push({state: "ok"});
container = [];
state = "firstavalue";
},
ovalue: function () {
stack.push({container: container, state: "ocomma", key: key});
container = [];
state = "firstavalue";
},
firstavalue: function () {
stack.push({container: container, state: "acomma"});
container = [];
state = "firstavalue";
},
avalue: function () {
stack.push({container: container, state: "acomma"});
container = [];
state = "firstavalue";
}
},
"]": {
firstavalue: function () {
var pop = stack.pop();
value = container;
container = pop.container;
key = pop.key;
state = pop.state;
},
acomma: function () {
var pop = stack.pop();
container.push(value);
value = container;
container = pop.container;
key = pop.key;
state = pop.state;
}
},
":": {
colon: function () {
if (Object.hasOwnProperty.call(container, key)) {
throw new SyntaxError("Duplicate key '" + key + "\"");
}
state = "ovalue";
}
},
",": {
ocomma: function () {
container[key] = value;
state = "okey";
},
acomma: function () {
container.push(value);
state = "avalue";
}
},
"true": {
go: function () {
value = true;
state = "ok";
},
ovalue: function () {
value = true;
state = "ocomma";
},
firstavalue: function () {
value = true;
state = "acomma";
},
avalue: function () {
value = true;
state = "acomma";
}
},
"false": {
go: function () {
value = false;
state = "ok";
},
ovalue: function () {
value = false;
state = "ocomma";
},
firstavalue: function () {
value = false;
state = "acomma";
},
avalue: function () {
value = false;
state = "acomma";
}
},
"null": {
go: function () {
value = null;
state = "ok";
},
ovalue: function () {
value = null;
state = "ocomma";
},
firstavalue: function () {
value = null;
state = "acomma";
},
avalue: function () {
value = null;
state = "acomma";
}
}
};
function debackslashify(text) {
@ -299,12 +299,12 @@ var json_parse = (function () {
// A regular expression is used to extract tokens from the JSON text.
// The extraction process is cautious.
var result,
tx = /^[\u0020\t\n\r]*(?:([,:\[\]{}]|true|false|null)|(-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)|"((?:[^\r\n\t\\\"]|\\(?:["\\\/trnfb]|u[0-9a-fA-F]{4}))*)")/;
var result;
var tx = /^[\u0020\t\n\r]*(?:([,:\[\]{}]|true|false|null)|(-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)|"((?:[^\r\n\t\\\"]|\\(?:["\\\/trnfb]|u[0-9a-fA-F]{4}))*)")/;
// Set the starting state.
state = 'go';
state = "go";
// The stack records the container, key, and state for each object or array
// that contains another object or array while processing nested structures.
@ -365,14 +365,14 @@ var json_parse = (function () {
state = e;
}
// The parsing is finished. If we are not in the final 'ok' state, or if the
// The parsing is finished. If we are not in the final "ok" state, or if the
// remaining source contains anything except whitespace, then we did not have
//a well-formed JSON text.
if (state !== 'ok' || (/[^\u0020\t\n\r]/.test(source))) {
throw state instanceof SyntaxError
if (state !== "ok" || (/[^\u0020\t\n\r]/.test(source))) {
throw (state instanceof SyntaxError)
? state
: new SyntaxError('JSON');
: new SyntaxError("JSON");
}
// If there is a reviver function, we recursively walk the new structure,
@ -381,23 +381,25 @@ var json_parse = (function () {
// value in an empty key. If there is not a reviver function, we simply return
// that value.
return typeof reviver === 'function'
return (typeof reviver === "function")
? (function walk(holder, key) {
var k, v, value = holder[key];
if (value && typeof value === 'object') {
var k;
var v;
var val = holder[key];
if (val && typeof val === "object") {
for (k in value) {
if (Object.prototype.hasOwnProperty.call(value, k)) {
v = walk(value, k);
if (Object.prototype.hasOwnProperty.call(val, k)) {
v = walk(val, k);
if (v !== undefined) {
value[k] = v;
val[k] = v;
} else {
delete value[k];
delete val[k];
}
}
}
}
return reviver.call(holder, key, value);
}({'': value}, ''))
return reviver.call(holder, key, val);
}({"": value}, ""))
: value;
};
}());