forked from mirrors/Scribe.js
122 lines
No EOL
3.2 KiB
JavaScript
122 lines
No EOL
3.2 KiB
JavaScript
export function parse(str, reviver) {
|
|
return JSON.parse(str, (k, v) => {
|
|
let rv;
|
|
if (typeof v === 'string') {
|
|
if (/^Promise \{(.*?)}$/g.test(v)) {
|
|
return new Promise((r, e) => 0);
|
|
} else if (/^function ([a-zA-Z0-9_\$]*?)\((.*?)\)\s?\{(.*?)}$/g.test(rv = v.replace(/\n/g, ''))) {
|
|
try {
|
|
let x;
|
|
eval(`x = ${v}`);
|
|
if (x) {
|
|
return x;
|
|
}
|
|
} catch (e) {
|
|
// ignore
|
|
}
|
|
}
|
|
|
|
try {
|
|
if ((rv = new RegExp(v)).toString() === v) {
|
|
return rv;
|
|
}
|
|
} catch (e) {
|
|
// ignore
|
|
}
|
|
}
|
|
|
|
return v;
|
|
});
|
|
}
|
|
|
|
const stringifyOnce = function (obj, replacer, indent) {
|
|
var printedObjects = [];
|
|
var printedObjectKeys = [];
|
|
|
|
function printOnceReplacer(key, value) {
|
|
if (printedObjects.length > 2000) { // browsers will not print more than 20K, I don't see the point to allow 2K.. algorithm will not be fast anyway if we have too many objects
|
|
return 'object too long';
|
|
}
|
|
var printedObjIndex = false;
|
|
printedObjects.forEach(function (obj, index) {
|
|
if (obj === value) {
|
|
printedObjIndex = index;
|
|
}
|
|
});
|
|
|
|
if (key == '') { //root element
|
|
printedObjects.push(obj);
|
|
printedObjectKeys.push("root");
|
|
return value;
|
|
}
|
|
|
|
else if (printedObjIndex + "" != "false" && typeof(value) == "object") {
|
|
if (printedObjectKeys[printedObjIndex] == "root") {
|
|
return "(pointer to root)";
|
|
} else {
|
|
return "(see " + ((!!value && !!value.constructor) ? value.constructor.name.toLowerCase() : typeof(value)) + " with key " + printedObjectKeys[printedObjIndex] + ")";
|
|
}
|
|
} else {
|
|
|
|
var qualifiedKey = key || "(empty key)";
|
|
printedObjects.push(value);
|
|
printedObjectKeys.push(qualifiedKey);
|
|
if (replacer) {
|
|
return replacer(key, value);
|
|
} else {
|
|
return value;
|
|
}
|
|
}
|
|
}
|
|
|
|
return JSON.stringify(obj, printOnceReplacer, indent);
|
|
};
|
|
|
|
// http://www.z-car.com/blog/programming/how-to-escape-mongo-keys-using-node-js-in-a-flash
|
|
function escapeKeys(obj) {
|
|
if (!(Boolean(obj) && typeof obj == 'object'
|
|
&& Object.keys(obj).length > 0)) {
|
|
return false;
|
|
}
|
|
|
|
Object.keys(obj).forEach(function (key) {
|
|
if (typeof(obj[key]) == 'object') {
|
|
escapeKeys(obj[key]);
|
|
} else {
|
|
if (key.indexOf('.') !== -1) {
|
|
var newkey = key.replace(/\./g, '_dot_');
|
|
obj[newkey] = obj[key];
|
|
delete obj[key];
|
|
}
|
|
if (key.indexOf('$') !== -1) {
|
|
var newkey = key.replace(/\$/g, '_amp_');
|
|
obj[newkey] = obj[key];
|
|
delete obj[key];
|
|
}
|
|
}
|
|
});
|
|
|
|
return true;
|
|
}
|
|
|
|
export function stringify(obj, replacer, spaces) {
|
|
const objStr = stringifyOnce(obj, (k, v)=> {
|
|
if (typeof v !== 'undefined' && v !== null) {
|
|
if (typeof v.then === 'function') {
|
|
return 'Promise { <pending> }'
|
|
} else if (typeof v === 'function') {
|
|
return v.toString().replace(/\[native code]/gm, '[native]');
|
|
} else if (v instanceof RegExp) {
|
|
return v.toString();
|
|
}
|
|
}
|
|
|
|
return v;
|
|
}, spaces);
|
|
|
|
const objCpy = JSON.parse(objStr);
|
|
|
|
escapeKeys(objCpy);
|
|
|
|
return JSON.stringify(objCpy);
|
|
} |