Skip to content

Instantly share code, notes, and snippets.

@k-maru
Created January 9, 2014 12:16
Show Gist options
  • Save k-maru/8333223 to your computer and use it in GitHub Desktop.
Save k-maru/8333223 to your computer and use it in GitHub Desktop.
json loose parser
if(!JSON){
JSON = {};
}
(function(global, undef){
"use strict";
var ch,
pos = 0,
text,
error = function (m) {
throw {
name: "SyntaxError",
message: m,
at: pos,
text: text
};
},
escapeChars = {
"\"": "\"",
"\\": "\\",
"/": "/",
b: "\b",
f: "\f",
n: "\n",
r: "\r",
t: "\t"
},
skip = function(){
while (ch && ch <= " ") {
next();
}
},
next = function () {
ch = text.charAt(pos);
pos += 1;
return ch;
},
string = function(){
var quote,
result = "",
uffff, i, hex;
if(ch === '"' || ch === "'"){
quote = ch;
while(next()){
if(ch === quote){
next();
return result;
}
if(ch === "\\"){
if (ch === 'u') {
uffff = 0;
for (i = 0; i < 4; i += 1) {
hex = parseInt(next(), 16);
if (!isFinite(hex)) {
break;
}
uffff = uffff * 16 + hex;
}
result += String.fromCharCode(uffff);
} else if (typeof escapeChars[ch] === 'string') {
result += escapeChars[ch];
} else {
break;
}
} else {
result += ch;
}
}
}
error("Bad string");
},
object = function(){
var key,
result = {};
if (ch === "{") {
next();
skip();
if (ch === "}") {
next();
return result; // empty object
}
while (ch) {
key = value(true);
skip();
if(ch !== ":"){
error("Bad object");
}
next();
if (Object.hasOwnProperty.call(result, key)) {
error("Duplicate key \"" + key + "\"");
}
result[key] = value();
skip();
if (ch === "}") {
next();
return result;
}
if(ch !== ","){
error("Bad object");
}
next();
skip();
}
}
error("Bad object");
},
array = function () {
var result = [];
if (ch === "[") {
next();
skip();
if (ch === "]") {
next();
return result; // empty array
}
while (ch) {
result.push(value());
skip();
if (ch === ']') {
next();
return result;
}
next();
skip();
}
}
error("Bad array");
},
loose = function(){
var result = "";
if(ch === "{"){
return object();
}
if(ch === "["){
return array();
}
if(ch === "\"" || ch === "'"){
return string();
}
while(ch){
if(ch === "," || ch === ":" || ch === "]" || ch === "}"){
return convert(result);
}
result += ch;
next();
}
return convert(result);
},
convert = function(val){
var upperVal;
if(!val){
return val;
}
//trim
val = val.toString().replace(/(^\s+)|(\s+$)/g, "");
upperVal = val.toUpperCase();
if(upperVal === "TRUE" || upperVal === "FALSE"){
return upperVal === "TRUE";
}
if(upperVal === "NULL"){
return null;
}
if(upperVal === "NaN"){
return NaN;
}
if(upperVal === "UNDEFINED"){
return undef;
}
if(upperVal === "INFINITY"){
return Infinity;
}
// isNumeric
if(!isNaN( parseFloat(val) ) && isFinite( val )){
return parseFloat(val);
}
return val;
},
value = function(primitive){
skip();
switch (ch) {
case "{":
if(primitive){
error("Bad value");
}
return object();
case "[":
if(primitive){
error("Bad value");
}
return array();
case "\"":
case "'":
return string();
default:
return loose();
}
};
JSON.parseLoose = function(source, reviver){
var result;
ch = " ";
pos = 0;
text = source;
result = value();
return typeof reviver === "function" ? (function walk(holder, key) {
var k, v, value = holder[key];
if (value && typeof value === "object") {
for (k in value) {
if (Object.prototype.hasOwnProperty.call(value, k)) {
v = walk(value, k);
if (v !== undefined) {
value[k] = v;
} else {
delete value[k];
}
}
}
}
return reviver.call(holder, key, value);
}({'': result}, ''))
: result;
}
})(window);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment