查找键包含点并替换为@

时间:2017-04-22 21:31:09

标签: javascript node.js mongodb

我有嵌套对象,可以在任何深度都有任意数量的键。 我想替换"。"在所有键(如果包含)中使用" @"我们如何以有效的方式做到这一点。

示例节点js对象

obj:{
        "BotBuilder.Data.SessionState": {
            "lastAccess": 1492886892545,
            "version": 14,
            "callstack": [
                {
                    "id": "*:/",
                    "state": {
                        "BotBuilder.Data.WaterfallStep": 0,
                        "BotBuilder.Data.Intent": "welcomeDialog"
                    }
                }
            ]
        }

目前我正在使用硬编码解决方案,但任何关键都可以在任何级别的对象中包含"。"我想要一般化的方法来解决这个问题

我的代码:

replaceDot:function(doc){
    var finalobj={}
    var finaldata={}
    var finalcallstack=new Array();
    console.log("doc==>",doc)
    var callstack=doc["data"]["BotBuilder.Data.SessionState"]["callstack"]
    for(var i = 0; i < callstack.length; i++) {
        var tempcallstack={}
        if("BotBuilder.Data.WaterfallStep" in callstack[i]["state"]){
            tempcallstack["id"]=callstack[i]["id"]
            var tempstate={}
            tempstate["state"]=callstack[i]["state"]
            tempstate["state"]["BotBuilder@Data@WaterfallStep"]=tempstate["state"]["BotBuilder.Data.WaterfallStep"]
            tempstate["state"]["BotBuilder@Data@Intent"]=tempstate["state"]["BotBuilder.Data.Intent"]
            delete tempstate["state"]["BotBuilder.Data.WaterfallStep"]
            delete tempstate["state"]["BotBuilder.Data.Intent"]
            tempcallstack["state"]=tempstate["state"];
            finalcallstack.push(tempcallstack);
        }
        else{
            finalcallstack.push(callstack[i]);
        }
    }   
    var obj={}
    finalobj["lastAccess"]=doc["data"]["BotBuilder.Data.SessionState"]["lastAccess"]
    finalobj["version"]=doc["data"]["BotBuilder.Data.SessionState"]["version"]
    finalobj["callstack"]=finalcallstack;
    obj["BotBuilder@Data@SessionState"]=finalobj
    var secondrootobj={"BotBuilder@Data@SessionState":finalobj}
    return secondrootobj;
}

1 个答案:

答案 0 :(得分:1)

这是一个获取对象或数组的函数,以及该对象的键的targetreplacement值。然后,它将返回一个新对象,其中target的实例在生成的对象的键中被replacement替换(使用String.prototype.replace)。

var substituteKeyDeep = function(obj, target, replacement) {
    // Get the type of the object. Array for arrays, Object for objects, null for anything else.
    try {
        var type = obj.constructor === Array ? Array
          : (obj.constructor === Object ? Object : null);
    } catch (err) {
        // A try/catch is actually necessary here. This is because trying to access the `constructor` property
        // of some values throws an error. For example `null.constructor` throws a TypeError.
        var type = null;
    }
    
    if (type === Array) {
        // Simply do a recursive call on all values in array
        var ret = [];
        for (var i = 0, len = obj.length; i < len; i++) {
            ret[i] = substituteKeyDeep(obj[i], target, replacement);
        }
    } else if (type === Object) {
        // Do a recursive call on all values in object, AND substitute key values using `String.prototype.replace`
        var ret = {};
        for (var k in obj) {
            ret[k.replace(target, replacement)] = substituteKeyDeep(obj[k], target, replacement);
        }
    } else {
        // For values that aren't objects or arrays, simply return the value
        var ret = obj;
    }
    
    return ret;
};

var data = {
    "BotBuilder.Data.SessionState": {
        "lastAccess": 1492886892545,
        "version": 14,
        "callstack": [
            {
                "id": "*:/",
                "state": {
                    "BotBuilder.Data.WaterfallStep": 0,
                    "BotBuilder.Data.Intent": "welcomeDialog"
                }
            }
        ]
    }
};

var dataWithRenamedKeys = substituteKeyDeep(data, /\./g, '@');

console.log(dataWithRenamedKeys);

请注意,在示例中,替换值(/\./g)是正则表达式,而不是字符串。这是因为需要使用全局修饰符(g)的正则表达式来替换对象键中所有实例,而不仅仅是第一个实例。

编辑:快速免责声明!如果使用具有循环引用的对象调用substituteKeyDeep,此解决方案将超出堆栈。