使用node.js循环遍历JSON

61

我有一个 JSON 文件需要遍历,如下所示...

{
    "device_id": "8020",
    "data": [{
        "Timestamp": "04-29-11 05:22:39 pm",
        "Start_Value":  0.02,
        "Abstract": 18.60,
        "Editor": 65.20
    }, {
        "Timestamp": "04-29-11 04:22:39 pm",
        "End_Value":  22.22,
        "Text": 8.65,
        "Common": 1.10,
        "Editable": "true",
        "Insert": 6.0
    }]
}

data中的键并不总是相同的(我只是举了一些例子,实际上有20个不同的键),因此,我不能设置我的脚本来静态地引用它们以获取值。

否则我可以这样说

var value1 = json.data.Timestamp;
var value2 = json.data.Start_Value;
var value3 = json.data.Abstract;
etc

过去我曾在数据节点上使用简单的foreach循环...

foreach ($json->data as $key => $val) {
    switch($key) {
        case 'Timestamp':
            //do this;
        case: 'Start_Value':
            //do this
    }
}

但不想阻止脚本。有什么想法吗?

9个回答

104

你可以通过以下方法遍历 JavaScript 对象:

for(var attributename in myobject){
    console.log(attributename+": "+myobject[attributename]);
}

myobject可能是您的json数据


2
这个是否是异步行为? - crawf
4
不,它不是异步的,但我不知道为什么它应该是异步的。Node.js非常快。如果你的对象中有成千上万个键,我能理解为什么要使用异步操作,但20个键并不需要。 - Van Coding
我明白你的意思!这对我来说都是非常新的东西,所以我只想坚持最佳实践!:) - crawf
1
嗨!只是好奇,如果有成千上万个键,我们该怎么办?意识到这篇文章已经很旧了。 - Ash Oldershaw
在2021年10月完美运行。 - DragonFire

26

我建议利用nodeJS永远是ES5的事实。记住这不是浏览器,您可以依赖语言在稳定性上的实现。话虽如此,我建议在nodeJS中永远不要使用for-in循环,除非您真的想在原型链上进行深度递归。对于简单传统的循环,我建议充分利用ES5中的Object.keys方法。如果您查看以下的JSPerf测试,尤其是如果您使用Chrome(因为它与nodeJS具有相同的引擎),您将可以大致了解使用此方法比使用for-in循环快多少(约快10倍)。以下是代码示例:

 var keys = Object.keys( obj );
 for( var i = 0,length = keys.length; i < length; i++ ) {
     obj[ keys[ i ] ];
 }

1
我也喜欢Object.keys方法...对你的建议进行了一点改进,但如果你使用反向for循环,速度会更快。当然,这仅适用于迭代顺序不重要的情况!虽然由于对象键返回的顺序没有保证,因此顺序是否重要可能是一个无关紧要的问题 ;)http://jsperf.com/forward-vs-reverse-for-loop[code] var keys = Object.keys(obj); for (i = keys.length; i--;) { obj[keys[i]]; } [/code] - Austin Floyd
最好使用let而不是var:for(let i = 0; length = keys.length; i < length; i++) - Seth Eden

24

在循环中,您可能还希望使用 hasOwnProperty

for (var prop in obj) {
    if (obj.hasOwnProperty(prop)) {
        switch (prop) {
            // obj[prop] has the value
        }
    }
}

node.js是单线程的,这意味着您的脚本无论如何都会被阻塞。请记住,V8(node.js使用的Google的JavaScript引擎)将JavaScript编译为机器代码,这意味着大多数基本操作非常快速,循环遍历具有100个键的对象可能只需要几纳秒。

但是,如果您在循环内执行了更多操作,并且不想立即阻塞,可以尝试像这样做:

switch (prop) {
    case 'Timestamp':
        setTimeout(function() { ... }, 5);
        break;
    case 'Start_Value':
        setTimeout(function() { ... }, 10);
        break;
}

如果您的循环正在执行一些非常耗费CPU资源的工作,您将需要生成一个子进程来处理该工作,或者使用Web Workers


hasOwnProperty看起来很有趣,我可能会将其合并到循环中。循环内的工作并不那么繁重。只需要将给定的值添加到数据库中即可。需要进行一些SQL格式化处理。 - crawf

6

我最喜欢的方法是:

var objectKeysArray = Object.keys(yourJsonObj)
objectKeysArray.forEach(function(objKey) {
    var objValue = yourJsonObj[objKey]
})

1
感谢您的帮助,我知道这个问题很旧,但我花了很多时间寻找解决方案,而您的解决方案对我非常有用,只是为了使其正常工作,我添加了属性到var objValue = yourJsonObj [objKey] .properties @Tharanga。 - DanyMartinez_

6

如果您想避免阻塞,这只对非常大的循环才是必要的,那么请将循环内容包装在一个名为process.nextTick(function(){<contents of loop>})的函数中,该函数会延迟执行直到下一次tick,从而有机会处理来自其他异步函数的挂起调用。


4
如果我们使用nodeJS,我们应该充分利用它提供的不同库。内置函数像each(),map(),reduce()以及来自underscoreJS的许多其他函数可以减少我们的工作量。以下是一个示例。
    var _=require("underscore");
    var fs=require("fs");

    var jsonObject=JSON.parse(fs.readFileSync('YourJson.json', 'utf8'));


    _.map( jsonObject, function(content) {
        _.map(content,function(data){
           if(data.Timestamp)
              console.log(data.Timestamp)          
           })
      })

3

有点晚了,但我相信以下内容可以进一步澄清。

你也可以通过简单的循环遍历JSON数组,例如:

for(var i = 0; i < jsonArray.length; i++)
{
    console.log(jsonArray[i].attributename);
}

如果您有一个JSON对象并且想要循环遍历其中的所有内部对象,那么您首先需要获取所有键名并将其放入一个数组中,然后通过遍历这些键名去检索对象,例如:
var keys = Object.keys(jsonObject);
for(var i = 0; i < keys.length; i++) 
{
    var key = keys[i];
    console.log(jsonObject.key.attributename);
}

2
不确定是否有帮助,但是似乎有一个用于异步迭代的库在这里托管:

https://github.com/caolan/async
Async是一个实用模块,为处理异步JavaScript提供了直观而强大的函数。虽然最初是为node.js设计的,但也可以直接在浏览器中使用。
Async提供了约20个函数,包括常见的“functional”函数(map、reduce、filter、forEach...),以及一些用于异步控制流的常见模式(parallel、series、waterfall...)。所有这些函数都假定您遵循node.js提供的惯例,即将单个回调作为异步函数的最后一个参数。

1

看看Traverse。它可以递归地遍历对象树,每个节点都有许多不同的对象可以访问 - 当前节点的键、当前节点的值、当前节点的父节点、当前节点的完整键路径等等。https://github.com/substack/js-traverse。我已经成功地将其用于我想要清除循环引用的对象以及在需要进行深度克隆并转换各种数据位时。这里是一些从他们的示例中提取的代码,让你了解它的功能。

var id = 54;
var callbacks = {};
var obj = { moo : function () {}, foo : [2,3,4, function () {}] };

var scrubbed = traverse(obj).map(function (x) {
    if (typeof x === 'function') {
        callbacks[id] = { id : id, f : x, path : this.path };
        this.update('[Function]');
        id++;
    }
});

console.dir(scrubbed);
console.dir(callbacks);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接