获取当前 JSON 节点的完全限定名称

Get fully qualified name of current JSON node

本文关键字:定名称 节点 JSON 获取      更新时间:2023-09-26

给定一个Javascript对象,如何遍历每个属性并获取每个节点的完全限定名称? 我正在尝试这样的事情:

var test = {
    "axes" : [{ 
        "stackType": "100%", 
        "testObject": {
            "testProperty": "found"
        },
        "minimum": 0
    }, {
        "gridColor": "#test", 
        "testArray": [
            {"jelly": 2}, {"jam": 3}
        ],
        "gridAlpha": 1
    }]
};
iterate(test);
function iterate(obj, parents) {
    if(!parents) { var parents = []; }
    for (var property in obj) {
        parents.push(property);
        if (obj.hasOwnProperty(property)) {
            if (typeof obj[property] == "object") { 
                iterate(obj[property], parents);
            } 
            else if (obj[property].constructor == Array) {
                for (var i = 0; i < obj[property].length; i++) {
                    iterate(obj[property][i], parents);
                }
            }
            else {
                console.log(parents + " : " + obj[property]);
            }
        }
    }
}

但是父数组只是不断被添加到。 我认为这是因为 Javascript 通过引用而不是按值处理数组。

我想要的输出是这样的:

axes, 0, stackType : 100%
axes, 0, testObject, testProperty : found
axes, 0, minimum : 0
axes, 1, gridColor: #test
axes, 1, testArray, 0, jelly: 2
axes, 1, testArray, 1, jam: 3
axes, 1, gridAlpha: 1

但相反,我只是添加了每个新属性,并且列表永远不会重置。

在循环中,您需要创建传入数组的副本parents并将property附加到该数组中,并在递归调用中传递该副本。否则,您只是在修改同一个数组。

var test = {
  "axes": [{
    "stackType": "100%",
    "testObject": {
      "testProperty": "found"
    },
    "minimum": 0
  }, {
    "gridColor": "#test",
    "testArray": [{
      "jelly": 2
    }, {
      "jam": 3
    }],
    "gridAlpha": 1
  }]
};
iterate(test);
function iterate(obj, parents) {
  if (!parents) {
    var parents = [];
  }
  for (var property in obj) {
    // changed line:
    var path = [].concat(parents, property);
    if (obj.hasOwnProperty(property)) {
      if (typeof obj[property] == "object") {
        iterate(obj[property], path); // changed
      } else if (obj[property].constructor == Array) {
        for (var i = 0; i < obj[property].length; i++) {
          iterate(obj[property][i], path); // changed
        }
      } else {
        // changed so you can see it without opening the console
        logLine(path.join(', ') + " : " + obj[property]);
      }
    }
  }
}
function logLine(line) {
  // show in console and in HTML
  console.log(line);
  document.getElementById('output').textContent += line + ''n';
}
<pre id="output"></pre>