【问题标题】:Javascript: deep walk/iterate through object keysJavascript:深入遍历/遍历对象键
【发布时间】:2018-07-15 21:43:40
【问题描述】:

我正在尝试在 Mongo 中索引各种 JSON 对象。有时,JSON 对象在某处有一个包含 . 的键,这让 Mongo 抱怨:

MongoError: The dotted field 'foo (e.g. bar)' in 'key.0.prop foo (e.g. bar)' is not valid for storage.

撇开这些数据不应该有这种键不谈,我想通过删除包含点的文本来调整带有点的键来临时处理这个问题。但是,这些键可以在对象中的任何位置,这需要同时遍历和修改键。例如,

{
  "foo": {
    "foo (e.g. bar)": "baz" 
  },
  "a": "b"
}

会变成

{
  "foo": {
    "foo": "baz" 
  },
  "a": "b"
}

基于我指定的一些函数transform(badKey)

遍历 Javascript 对象并根据某些标准修改键的最简单/最可靠的方法是什么?请注意,某些键可能嵌套了好几层,因此简单的键值迭代在这里不起作用。指向提供此功能的库的指针会很棒。

【问题讨论】:

标签: javascript json mongodb iteration traversal


【解决方案1】:

不使用 JSON.stringify,这是一种矫枉过正

function deepTransformKeys(obj) {
    if (obj && typeof obj === 'object') {
        var allKeys = Object.keys(obj);
        for(var i = 0 ; i < allKeys.length ; i++){
            var k = allKeys[i];

            var value = obj[k];
           if (isBadKey(k)) {
                var goodKey = transform(k);
                obj[goodKey] = value;
                delete obj[k];
           }
           if ( typeof value === 'object') {
               deepTransformKeys(value);
           }
        }
    }
    return obj;
}

你可以定义你想要的键和你想要转换它们的方式:

var GoodKeyRegex = /^\w+$/
function isBadKey(key) {
    return !GoodKeyRegex.test(key);
}

function transform(key) {
    return key.replace(/\W+/g, "");
}

简单的输入输出

var x = {
    "foo": {
        "foo (e.g. bar)": {
            "foo (e.g. bar)2": {
                "foo (e.g. bar)3" : {
                    "foo1": "bar1"
                }
            }
        }
    },
    "a": "b"
};

console.log('INPUT',JSON.stringify(x, null, ' '));
var y = deepTransformKeys(x);
console.log('---------------------------');
console.log('OUTPUT', JSON.stringify(y, null, ' '));

【讨论】:

    【解决方案2】:

    虽然我更喜欢 Paticks 的解决方案,但这是我对它使用递归的看法。我仍然认为最强大和最有效的方法是使用词法分析器和解析器并忽略语言本身。

    var json = {
      "foo": {
        "foo (e.g. bar)": "baz" 
      },
      "a": "b"
    }
    
    console.log(json)
    
    function replace (obj) {
      for ( var key in obj ) {
        
        if (!obj.hasOwnProperty(key)) {continue;}
        
        if ( typeof obj[key] === 'object' && obj[key] !== null ) {
          replace(obj[key])
          }
        if (key.indexOf('.')> -1) {
          var new_key = key.replace(/\./g,' ')
          obj[new_key] = obj[key];
          delete obj[key];
        }
      }
    }
    
    replace(json)
    
    console.log(json)

    【讨论】:

    • 如果你想迭代自己的可枚举键,你也可以这样做for (var key in obj) { if (!obj.hasOwnProperty(key)) continue; ...
    • @PatrickRoberts 补充说。你能告诉我为什么要仔细检查obj.hasOwnProperty(key) 吗?
    • 因为for...in 迭代了可枚举的自己的和继承的属性。这不是“双重”检查。
    猜你喜欢
    • 2014-07-06
    • 2017-08-30
    • 1970-01-01
    • 2017-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-13
    • 1970-01-01
    相关资源
    最近更新 更多