如何在JavaScript或Node.js中创建JSON序列化的安全对象

如何在JavaScript或Node.js中创建JSON序列化的安全对象,javascript,node.js,recursion,json,Javascript,Node.js,Recursion,Json,我的愿望是以一种“安全”的方式将给定对象编码为JSON。这用于记录Node.js中的任何抽象对象,但也可以应用于其他需要。我的研究将我指向节点中的util.inspect,但这不是有效的JSON,我的愿望是拥有有效的JSON,我可以稍后重新生成。因为一些错误实例可能存在递归问题,所以我需要限制响应。此外,在某些情况下,对对象的前向和后向引用也可能是一个问题,因此我希望避免重复条目。新答案 今天,如果有人在看这篇文章,我会用比我的原著更透彻的 原始答复: 我在下面回答我自己的问题,因为要想出一个

我的愿望是以一种“安全”的方式将给定对象编码为JSON。这用于记录Node.js中的任何抽象对象,但也可以应用于其他需要。我的研究将我指向节点中的util.inspect,但这不是有效的JSON,我的愿望是拥有有效的JSON,我可以稍后重新生成。因为一些错误实例可能存在递归问题,所以我需要限制响应。此外,在某些情况下,对对象的前向和后向引用也可能是一个问题,因此我希望避免重复条目。

新答案

今天,如果有人在看这篇文章,我会用比我的原著更透彻的


原始答复:

我在下面回答我自己的问题,因为要想出一个有效的解决方案有点困难。这是我找到的几个解决方案的组合,似乎效果很好

/* 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;

    }

}());
/*lib/clone-safe.js
*提供一种方法,用于创建对象的克隆而不使用冗余对象引用,并防止递归。
*克隆的值*应该*对于JSON.stringify(cloneSafe(myobj))始终是安全的
**/
(功能(){
var unde;//故意未定义的值
功能cloneSafe(obj,深度){
var refs=[];//对克隆对象的引用
深度=+depth>0&&+depth | | 6;//最大递归级别
var layerNumber=0;//正在检查的当前图层
var ret=clone(obj);//开始克隆
//清除引用检查
while(参考长度){
删除(refs.shift())。\复制;
}
//返回结果
返回ret;
//递归克隆法
功能克隆(obj){
if(typeof obj==“function”)返回未定义;//无函数复制
//处理3个简单类型,以及null或undefined
如果(null==obj | |“object”!=typeof obj)返回obj;
//处理日期
if(obj实例截止日期){
var copy=新日期();
copy.setTime(obj.getTime());
返回副本;
}
//句柄数组
if(阵列的obj实例){
var copy=[];
对于(变量i=0,len=obj.length;i=深度){
图层编号--;
返回未定义;
}
//处理循环引用和重复引用
如果(对象已复制)返回未定义;//已包含
对象复制=真;
参考推力(obj);
var copy={};
//导出原型
var m=obj.constructor&&obj.constructor.toString().match(/function\s+([^\(]+)/);
如果(m&&m[1])复制。_prototype=m[1];
//从任何错误中获取所需的属性
if(obj实例错误){
copy.message=obj.message | |“错误”;
如果(obj.stack)copy.stack=obj.stack;
如果(obj.number)copy.number=obj.number;
如果(obj.description)copy.description=obj.description;
如果(obj.name)copy.name=obj.name;
}
for(obj中的var attr){
如果(attr==“\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu复制”)继续;
如果(obj.hasOwnProperty(attr))copy[attr]=clone(obj[attr]);
}
if(对象原型){
for(对象原型中的var attr){
if(obj.prototype.hasOwnProperty(attr)&&typeof obj.prototype[attr]!=='function')copy[attr]=clone(obj.prototype[attr]);
删除obj.prototype[attr]。\uuuuuuuuuuuuu复制;//允许重新扫描原型
}
}
图层编号--;
返回副本;
}
//抛出新错误(“无法复制对象!其类型不受支持。”);
console.log(“无法复制obj!不支持的类型:%s”,类型为obj);
return undf;//无法克隆有问题的对象
}
}
//AMD/RequireJS
if(typeof define==“function”&&define.amd){
定义(“克隆安全”、[],function(){return cloneSafe;});
}
//Node.js/CommonJS
else if(模块类型!=“未定义”&&module.exports){
module.exports=cloneSafe;
}
//浏览器/脚本包括
否则{
//提供还原全局绑定的方法
var root=this;//服务器上的全局,浏览器中的窗口。
var previousCloneSafe=root.cloneSafe;//反向引用
cloneSafe.noConflict=函数(){
root.cloneSafe=以前的cloneSafe;
返回氯硝安全;
};
//绑定到全局对象
root.cloneSafe=cloneSafe;
}
}());

有一些额外的逻辑用于处理错误对象,并确保从所述错误和给定对象的原型中获得必要的数据。函数在响应中被明确忽略。当递归太深时,它将返回给定对象的未定义对象。

有一个本机javascript JSON对象,带有stringify方法,这是您所需要的,我想:

如果您的对象中有任何递归,在捕获其他错误时可能会发生,JSON.stringify就会爆炸…您忘记提到什么的本机?您在所有可用的浏览器上都检查过吗?