Last active
January 29, 2016 10:01
-
-
Save ironboy/68c928c50dd7e70580b3 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// A cool JSON reviver | |
// Thomas Frank 2015 | |
// MIT licensed | |
JSON.cool = (function(){ | |
var mem, findMem, base, toFind, settings = { | |
circulars: true, | |
dates: true, | |
functions: false, | |
regExps: true, | |
types: { | |
add:function(x){ | |
for(var i in x){this[i] = x[i];} | |
} | |
} | |
}; | |
function cool(key,val){ | |
var i, proto, valproto, tmp; | |
// new base object | |
if(!key){ | |
base = this[""]; | |
mem = [base]; | |
} | |
if(cool.circulars){ | |
// stringify circular | |
if(key && mem.indexOf(val)>=0){ | |
toFind = val; | |
findMem = []; | |
return '->circular->' + (val == base ? "" : findPath(base).substring(2)); | |
} | |
// parse circular | |
if(typeof val=="string" && val.indexOf('->circular->')===0){ | |
return getDataFromPath(base,val.split('->circular->')[1]); | |
} | |
// add objects/arrays to mem for circulars | |
if(typeof val == "object"){ mem.push(val); } | |
} | |
if(cool.dates){ | |
// parse date (auto stringified by js earlier) | |
if(val && this[key] == val && val.match && val.match(/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.\d+)?Z$/)){ | |
return new Date(val); | |
} | |
} | |
if(cool.functions){ | |
// stringify function | |
if(typeof val == "function"){ | |
return '->function->' + val; | |
} | |
// parse function | |
if(typeof val=="string" && val.indexOf('->function->')===0){ | |
return new construct(Function, | |
val.match(/\(([^\)]*)/)[1].split(','). | |
concat([val.substring( | |
val.indexOf('{')+1,val.lastIndexOf('}') | |
)]) | |
); | |
} | |
} | |
if(cool.regExps){ | |
// stringify regexp | |
if(val instanceof RegExp){ | |
return '->regexp->' + val; | |
} | |
// parse regexp | |
if(typeof val=="string" && val.indexOf('->regexp->')===0){ | |
tmp = val.substring(val.indexOf('/')+1,val.lastIndexOf('/')); | |
return new RegExp(tmp,val.split(tmp)[1].substring(1)); | |
} | |
} | |
// stringify prototype | |
if(typeof val == "object"){ | |
valproto = Object.getPrototypeOf(val || {}); | |
if(valproto !== Object.prototype){ | |
for(i in cool.types){ | |
proto = typeof cool.types[i] == "function" ? | |
cool.types[i].prototype : cool.types[i]; | |
if(proto === valproto){ | |
val._type = i; | |
} | |
} | |
return val; | |
} | |
} | |
// parse prototype | |
if(val && typeof val == "object" && typeof val._type == "string"){ | |
valproto = Object.create( | |
typeof cool.types[val._type] == "function" ? | |
cool.types[val._type].prototype : cool.types[val._type] | |
); | |
if(typeof cool.types[val._type] == "function"){ | |
valproto.constructor = cool.types[val._type]; | |
} | |
for(i in val){valproto[i] = val[i];} | |
delete valproto._type; | |
val = valproto; | |
} | |
return val; | |
} | |
function findPath(obj,path){ | |
findMem.push(obj); | |
var i,f, p; | |
path = path || ''; | |
for(i in obj){ | |
p = path + '.' + i; | |
if(obj[i] === toFind){return "*" + p; } | |
f = typeof obj[i] == "object" && findMem.indexOf(obj[i])<0 && findPath(obj[i],p); | |
if(f[0] == "*"){ return f; } | |
} | |
return path; | |
} | |
function getDataFromPath(obj,path){ | |
if(!path){return obj;} | |
path = path.split('.'); | |
while(obj && path.length){ | |
obj = obj[path.shift()]; | |
} | |
return obj; | |
} | |
// "Apply" a constructor; | |
function construct(constructor, args) { | |
function F() { | |
return constructor.apply(this, args); | |
} | |
F.prototype = constructor.prototype; | |
return new F(); | |
} | |
// Get prototype of polyfill - John Resig | |
if ( typeof Object.getPrototypeOf !== "function" ) { | |
if ( typeof "test".__proto__ === "object" ) { | |
Object.getPrototypeOf = function(object){ | |
return object.__proto__; | |
}; | |
} else { | |
Object.getPrototypeOf = function(object){ | |
// May break if the constructor has been tampered with | |
return object.constructor.prototype; | |
}; | |
} | |
} | |
// Cool settings | |
for(var i in settings){ | |
cool[i] = settings[i]; | |
} | |
return cool; | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment