{"ScriptPreparationCode":"var jsObj = {\r\n boolY: true,\r\n boolX: false,\r\n str: \u0027string\u0027,\r\n num: 123,\r\n obj: {},\r\n arr: [{ name: \u0027Alex\u0027, type: \u0027manager\u0027 }, { name: \u0027Bob\u0027, type: \u0027ceo\u0027 }],\r\n undef: undefined,\r\n null: null,\r\n};\r\n\r\nvar json = JSON.stringify(jsObj, null, 2);\r\n\r\nconsole.log({ json: json });\r\n\r\nfunction parseJSON_eval(json) {\r\n return eval(\u0060(${json})\u0060);\r\n}\r\n\r\nfunction parseJSON_ES4(json) {\r\n // Higher-order function to be used for detecting type\r\n var firstAndLastChars = function firstAndLastChars(first, last) {\r\n return function(str) {\r\n return str[0] === first \u0026\u0026 str[str.length - 1] === last;\r\n };\r\n };\r\n\r\n var isArray = firstAndLastChars(\u0027[\u0027, \u0027]\u0027);\r\n var isObj = firstAndLastChars(\u0027{\u0027, \u0027}\u0027);\r\n var hasDoubleQuotes = firstAndLastChars(\u0027\u0022\u0027, \u0027\u0022\u0027);\r\n var hasSingleQuotes = firstAndLastChars(\u0022\u0027\u0022, \u0022\u0027\u0022);\r\n\r\n var isNumber = function isNumber(str) {\r\n return \u002Bstr \u002B \u0027\u0027 === str;\r\n };\r\n\r\n var isString = function isString(str) {\r\n str = str.trim();\r\n return (hasSingleQuotes(str) || hasDoubleQuotes(str)) \u0026\u0026 str[str.length - 2] !== \u0027\\\\\u0027;\r\n };\r\n\r\n var removeFirstAndLastChar = function removeFirstAndLastChar(str) {\r\n str = str.trim();\r\n return str.substring(1).slice(0, str.length - 2) || \u0027\u0027;\r\n }; // Higher-order function to be used for splitting string\r\n\r\n var splitByChar = function splitByChar(base_char) {\r\n return function(str) {\r\n var result = [];\r\n var double_string_open = false;\r\n var single_string_open = false;\r\n var array_open = false;\r\n var object_open = false;\r\n var array_bracket_count = 0;\r\n var object_bracket_count = 0;\r\n var curr_str = \u0027\u0027;\r\n var prev_ch = \u0027\u0027;\r\n\r\n for (var i = 0; i \u003C str.length; i \u002B= 1) {\r\n var ch = str[i];\r\n\r\n if (ch === \u0027\u0022\u0027) {\r\n double_string_open = !double_string_open;\r\n }\r\n\r\n if (ch === \u0022\u0027\u0022) {\r\n single_string_open = !single_string_open;\r\n }\r\n\r\n if (ch === \u0027[\u0027) {\r\n array_bracket_count \u002B= 1;\r\n array_open = true;\r\n }\r\n\r\n if (ch === \u0027]\u0027) {\r\n array_bracket_count -= 1;\r\n\r\n if (array_bracket_count === 0) {\r\n array_open = false;\r\n }\r\n }\r\n\r\n if (ch === \u0027{\u0027) {\r\n object_bracket_count \u002B= 1;\r\n object_open = true;\r\n }\r\n\r\n if (ch === \u0027}\u0027) {\r\n object_bracket_count -= 1;\r\n\r\n if (object_bracket_count === 0) {\r\n object_open = false;\r\n }\r\n }\r\n\r\n if (ch === base_char \u0026\u0026 !double_string_open \u0026\u0026 !single_string_open \u0026\u0026 !array_open \u0026\u0026 !object_open) {\r\n if (curr_str !== \u0027\u0027) result.push(curr_str.trim());\r\n curr_str = \u0027\u0027;\r\n prev_ch = \u0027\u0027;\r\n } else {\r\n curr_str \u002B= ch;\r\n prev_ch = ch;\r\n }\r\n }\r\n\r\n if (curr_str !== \u0027\u0027) result.push(curr_str.trim());\r\n return result;\r\n };\r\n };\r\n\r\n var separeateStringByCommas = splitByChar(\u0027,\u0027);\r\n var separeateStringByColons = splitByChar(\u0027:\u0027);\r\n\r\n var parseJSONString = function parseJSONString(str, parent) {\r\n str = str.trim();\r\n if (isArray(str)) return separeateStringByCommas(removeFirstAndLastChar(str)).map(parseJSONString);\r\n\r\n if (isObj(str)) {\r\n var obj = {};\r\n\r\n var _obj = separeateStringByCommas(removeFirstAndLastChar(str)); // _obj is an array of strings with \u0027key: value\u0027\r\n\r\n _obj.forEach(function(val, i) {\r\n var key_val_pair = separeateStringByColons(val); // split into key, value\r\n\r\n if (key_val_pair.length === 2) {\r\n obj[parseJSONString(key_val_pair[0])] = parseJSONString(key_val_pair[1]);\r\n }\r\n });\r\n\r\n return obj;\r\n }\r\n\r\n if (isString(str)) return removeFirstAndLastChar(str).replace(/([\\\\]{1})([\\\\\\\u0022]{1})/g, \u0027$2\u0027);\r\n if (isNumber(str)) return \u002Bstr;\r\n if (str === \u0027null\u0027) return null;\r\n if (str === \u0027false\u0027) return false;\r\n if (str === \u0027true\u0027) return true;\r\n if (str === \u0027undefined\u0027) return undefined;\r\n throw new SyntaxError(\u0027Unexpected end of input\u0027);\r\n };\r\n\r\n return parseJSONString(json);\r\n}\r\n\r\nfunction parseJSON_ES6(json) {\r\n // Higher-order function to be used for detecting type\r\n const firstAndLastChars = function(first, last) {\r\n return str =\u003E str[0] === first \u0026\u0026 str[str.length - 1] === last;\r\n };\r\n const isArray = firstAndLastChars(\u0027[\u0027, \u0027]\u0027);\r\n const isObj = firstAndLastChars(\u0027{\u0027, \u0027}\u0027);\r\n const hasDoubleQuotes = firstAndLastChars(\u0027\u0022\u0027, \u0027\u0022\u0027);\r\n const hasSingleQuotes = firstAndLastChars(\u0022\u0027\u0022, \u0022\u0027\u0022);\r\n const isNumber = str =\u003E \u002Bstr \u002B \u0027\u0027 === str;\r\n const isString = function(str) {\r\n str = str.trim();\r\n return (hasSingleQuotes(str) || hasDoubleQuotes(str)) \u0026\u0026 str[str.length - 2] !== \u0027\\\\\u0027;\r\n };\r\n const removeFirstAndLastChar = function(str) {\r\n str = str.trim();\r\n return str.substring(1).slice(0, str.length - 2) || \u0027\u0027;\r\n };\r\n // Higher-order function to be used for splitting string\r\n const splitByChar = function(base_char) {\r\n return function(str) {\r\n var result = [];\r\n var double_string_open = false;\r\n var single_string_open = false;\r\n var array_open = false;\r\n var object_open = false;\r\n var array_bracket_count = 0;\r\n var object_bracket_count = 0;\r\n var curr_str = \u0027\u0027;\r\n var prev_ch = \u0027\u0027;\r\n for (var i = 0; i \u003C str.length; i \u002B= 1) {\r\n var ch = str[i];\r\n if (ch === \u0027\u0022\u0027) {\r\n double_string_open = !double_string_open;\r\n }\r\n if (ch === \u0022\u0027\u0022) {\r\n single_string_open = !single_string_open;\r\n }\r\n if (ch === \u0027[\u0027) {\r\n array_bracket_count \u002B= 1;\r\n array_open = true;\r\n }\r\n if (ch === \u0027]\u0027) {\r\n array_bracket_count -= 1;\r\n if (array_bracket_count === 0) {\r\n array_open = false;\r\n }\r\n }\r\n if (ch === \u0027{\u0027) {\r\n object_bracket_count \u002B= 1;\r\n object_open = true;\r\n }\r\n if (ch === \u0027}\u0027) {\r\n object_bracket_count -= 1;\r\n if (object_bracket_count === 0) {\r\n object_open = false;\r\n }\r\n }\r\n if (ch === base_char \u0026\u0026 !double_string_open \u0026\u0026 !single_string_open \u0026\u0026 !array_open \u0026\u0026 !object_open) {\r\n if (curr_str !== \u0027\u0027) result.push(curr_str.trim());\r\n curr_str = \u0027\u0027;\r\n prev_ch = \u0027\u0027;\r\n } else {\r\n curr_str \u002B= ch;\r\n prev_ch = ch;\r\n }\r\n }\r\n if (curr_str !== \u0027\u0027) result.push(curr_str.trim());\r\n return result;\r\n };\r\n };\r\n const separeateStringByCommas = splitByChar(\u0027,\u0027);\r\n const separeateStringByColons = splitByChar(\u0027:\u0027);\r\n const parseJSONString = function(str, parent) {\r\n str = str.trim();\r\n if (isArray(str)) return separeateStringByCommas(removeFirstAndLastChar(str)).map(parseJSONString);\r\n if (isObj(str)) {\r\n var obj = {};\r\n var _obj = separeateStringByCommas(removeFirstAndLastChar(str));\r\n // _obj is an array of strings with \u0027key: value\u0027\r\n _obj.forEach(function(val, i) {\r\n var key_val_pair = separeateStringByColons(val); // split into key, value\r\n if (key_val_pair.length === 2) {\r\n obj[parseJSONString(key_val_pair[0])] = parseJSONString(key_val_pair[1]);\r\n }\r\n });\r\n return obj;\r\n }\r\n if (isString(str)) return removeFirstAndLastChar(str).replace(/([\\\\]{1})([\\\\\\\u0022]{1})/g, \u0027$2\u0027);\r\n if (isNumber(str)) return \u002Bstr;\r\n if (str === \u0027null\u0027) return null;\r\n if (str === \u0027false\u0027) return false;\r\n if (str === \u0027true\u0027) return true;\r\n if (str === \u0027undefined\u0027) return undefined;\r\n throw new SyntaxError(\u0027Unexpected end of input\u0027);\r\n };\r\n return parseJSONString(json);\r\n}\r\n","TestCases":[{"Name":"eval","Code":"parseJSON_eval(json)","IsDeferred":false},{"Name":"ES4 (old JS, Siebel eScript)","Code":"parseJSON_ES4(json)","IsDeferred":false},{"Name":"ES6 (new JS)","Code":"parseJSON_ES6(json)","IsDeferred":false}]}