3

我正在使用一个 JSON 对象,它可以ids在任何叶子上都有一个属性。我想遍历该对象并找到该ids属性的所有实例并将每个 id 存储在一个集合中。

模拟 JSON 对象(该ids属性可能位于更深的属性位置)。

{
  "id": "b38a683d-3fb6-408f-9ef6-f4b853ed1193",
  "foo": {
    "ids": [
      {
        "id": "bd0bf3bd-d6b9-4706-bfcb-9c867e47b881"
      },
      {
        "id": "d1cc529d-d5d2-4460-b2bb-acf24a7c5999"
      },
      {
        "id": "b68d0c8c-548e-472f-9b01-f25d4b199a71"
      }
    ],
    "baz": "super"
  },
  "bar": {
    "ids": [
      {
        "id": "bd0bf3bd-d6b9-4706-bfcb-9c867e47b881"
      },
      {
        "id": "d1cc529d-d5d2-4460-b2bb-acf24a7c5999"
      },
      {
        "id": "b68d0c8c-548e-472f-9b01-f25d4b199a71"
      }
    ]
  }
}

我正在使用下面的代码来遍历上面的 JSON。

var jsonFile = require('./file_test.json'); // the above in my local directory

function traverse(obj, ids) {
  for (var prop in obj) {
    if (typeof obj[prop] == "object" && obj[prop]) {
      if (prop == 'ids') {
        for (var i = obj[prop].length - 1; i >= 0; i--) {
          ids.push(obj[prop][i]._id);
        };
      }
      traverse(obj[prop], ids);
    }
  }
}

var ids = new Array();
traverse(jsonFile, ids);

console.log('ids', ids);

上述内容如下:

ids
[
  'b68d0c8c-548e-472f-9b01-f25d4b199a71',
  'd1cc529d-d5d2-4460-b2bb-acf24a7c5999',
  'bd0bf3bd-d6b9-4706-bfcb-9c867e47b881',
  'b68d0c8c-548e-472f-9b01-f25d4b199a71',
  'd1cc529d-d5d2-4460-b2bb-acf24a7c5999',
  'bd0bf3bd-d6b9-4706-bfcb-9c867e47b881'
]

虽然我的代码有效,但我不相信我这样做是最有效或最好的方式。有没有更好的方法来查找该ids属性的所有实例?也许没有传入一个数组而是返回一个?ids或者使用数组设置回调?

4

5 回答 5

7

如果数据实际上是 JSON 字符串,而不是 JavaScript 对象,您可以有如下内容:

// assuming `json` is the data string
var ids = [];
var data = JSON.parse(json, function(key, value) {
    if (key === "id") 
        ids.push(value);

    return value;
});

请参阅reviverJSON.parse方法

于 2013-04-13T23:15:39.863 回答
3

你所拥有的很好,但这有点短并使用 .map 函数:

var jsonFile = require('./file_test.json'); // the above in my local directory
function traverse(obj) {
    var ids = [];
    for (var prop in obj) {
        if (typeof obj[prop] == "object" && obj[prop]) {
            if (prop == 'ids') {
                ids = obj[prop].map(function(elem){
                   return elem.id;
               })
            }
            ids =ids.concat(traverse(obj[prop]));
        }
    }
    return ids;
}

var ids =traverse(jsonFile);

console.log('ids', ids);
于 2013-04-13T21:53:43.317 回答
0

假设 ES5 可以原生或通过shim获得:

function gimmeIds(obj) {
    return Object.keys(obj||{})
        .reduce(function(ids, key) {
            if(key === 'ids') {
                return ids.concat(obj[key].map(function(idObj) {
                    return idObj.id;
                }));
            }

            if(obj[key] && typeof obj[key] == 'object') {
                return ids.concat(gimmeIds(obj[key]));
            }

            return ids;
        }, []);
}
于 2013-04-14T02:03:43.300 回答
0

你基本上想做的是对这个 JSON 对象进行树搜索,对吗?因此,如果我们假设它ids始终是一个叶子,那么我们不需要traverse这些节点,因为我们知道它们在叶子上并且将包含我们想要的内容。

  • 更改if {...} traverse if {...} else {traverse}

如果可以将数据结构更改ids为字符串列表而不是对象列表,那么您将能够保存对数组的迭代并将其合并到ids传入的数组中,但这完全取决于上下文以及您是否可以进行此更改!

对不起,我没有更多的帮助!

于 2013-04-13T21:41:38.070 回答
0

使用对象扫描,这变得非常简单。请注意,您可以轻松地指定目标(在这种情况下**.ids[*].id

// const objectScan = require('object-scan');

const data = { id: 'b38a683d-3fb6-408f-9ef6-f4b853ed1193', foo: { ids: [{ id: 'bd0bf3bd-d6b9-4706-bfcb-9c867e47b881' }, { id: 'd1cc529d-d5d2-4460-b2bb-acf24a7c5999' }, { id: 'b68d0c8c-548e-472f-9b01-f25d4b199a71' }], baz: 'super' }, bar: { ids: [{ id: 'bd0bf3bd-d6b9-4706-bfcb-9c867e47b881' }, { id: 'd1cc529d-d5d2-4460-b2bb-acf24a7c5999' }, { id: 'b68d0c8c-548e-472f-9b01-f25d4b199a71' }] } };

const findIds = (input) => objectScan(['**.ids[*].id'], { rtn: 'value' })(input);

console.log(findIds(data));
/* => [ 'b68d0c8c-548e-472f-9b01-f25d4b199a71',
  'd1cc529d-d5d2-4460-b2bb-acf24a7c5999',
  'bd0bf3bd-d6b9-4706-bfcb-9c867e47b881',
  'b68d0c8c-548e-472f-9b01-f25d4b199a71',
  'd1cc529d-d5d2-4460-b2bb-acf24a7c5999',
  'bd0bf3bd-d6b9-4706-bfcb-9c867e47b881' ]
 */
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/object-scan@13.7.1"></script>

免责声明:我是对象扫描的作者

于 2020-12-27T01:34:30.740 回答