我的愿望是将给定对象编码为JSON的“安全”方式。这是为了记录Node.js中的任何抽象对象,但也可以应用于其他需求。我的研究向我指出了Node中的util.inspect,但这不是有效的JSON,我希望有一个有效的JSON,我可以在以后重新补充。因为某些Error实例可能有递归问题,所以我需要限制响应。此外,在某些情况下,对象的前向和后向引用也可能是一个问题,因此我希望避免重复的条目。
答案 0 :(得分:0)
我在回答下面的问题,因为提出一个有效的解决方案有点困难。这是我发现的一些解决方案的组合,似乎运作良好。
/* lib/clone-safe.js
* provides a method for creating a clone of an object without redundant object references, and protected from recursion.
* The cloned value *should* always be safe for JSON.stringify(cloneSafe(myobj))
**/
(function(){
var undef; //intentionally undefined value
function cloneSafe(obj,depth){
var refs = []; //reference to cloned objects
depth = +depth > 0 && +depth || 6; //max recursion level
var layerNumber = 0; //current layer being checked
var ret = clone(obj); //start cloning
//cleanup reference checks
while(refs.length) {
delete (refs.shift()).___copied;
}
//return the result
return ret;
//recursive clone method
function clone(obj) {
if (typeof obj == "function") return undef; //no function replication
// Handle the 3 simple types, and null or undefined
if (null == obj || "object" != typeof obj) return obj;
// Handle Date
if (obj instanceof Date) {
var copy = new Date();
copy.setTime(obj.getTime());
return copy;
}
// Handle Array
if (obj instanceof Array) {
var copy = [];
for (var i = 0, len = obj.length; i < len; i++) {
copy[i] = clone(obj[i]);
}
return copy;
}
// Handle Object
if (obj instanceof Object) {
//max recursion reached
if (++layerNumber >= depth) {
layerNumber--;
return undef;
}
//handle circular and duplicate references
if (obj.___copied) return undef; //already included
obj.___copied = true;
refs.push(obj);
var copy = {};
//export prototype
var m = obj.constructor && obj.constructor.toString().match(/function\s+([^\(]+)/);
if (m && m[1]) copy._prototype = m[1];
//get expected properties from any error
if (obj instanceof Error) {
copy.message = obj.message || "Error";
if (obj.stack) copy.stack = obj.stack;
if (obj.number) copy.number = obj.number;
if (obj.description) copy.description = obj.description;
if (obj.name) copy.name = obj.name;
}
for (var attr in obj) {
if (attr == "___copied") continue;
if (obj.hasOwnProperty(attr)) copy[attr] = clone(obj[attr]);
}
if (obj.prototype) {
for (var attr in obj.prototype) {
if (obj.prototype.hasOwnProperty(attr) && typeof obj.prototype[attr] !== 'function') copy[attr] = clone(obj.prototype[attr]);
delete obj.prototype[attr].___copied; //allow prototypes to be re-scanned
}
}
layerNumber--;
return copy;
}
//throw new Error("Unable to copy obj! Its type isn't supported.");
console.log("Unable to copy obj! Unsupported type: %s", typeof obj);
return undef; //unable to clone the object in question
}
}
// AMD / RequireJS
if (typeof define === "function" && define.amd) {
define("clone-safe",[],function(){ return cloneSafe; });
}
// Node.js / CommonJS
else if (typeof module !== "undefined" && module.exports) {
module.exports = cloneSafe;
}
// browser/script include
else {
//provide a method for reverting global binding
var root = this; //global on the server, window in the browser.
var previousCloneSafe = root.cloneSafe; //backreference
cloneSafe.noConflict = function(){
root.cloneSafe = previousCloneSafe;
return cloneSafe;
};
//bind to the global object
root.cloneSafe = cloneSafe;
}
}());
有一些额外的逻辑可以处理错误的对象,并确保从所述错误和给定对象的原型中获取必要的数据。响应中明确忽略了这些函数。当递归过深时,它将返回给定对象的未定义。
答案 1 :(得分:0)
有一个原生的javascript JSON对象,带有stringify方法,这就是你所需要的,我认为:http://www.javascripture.com/JSON#stringify