【问题标题】:Looping through JSON with node.js使用 node.js 循环 JSON
【发布时间】:2011-08-15 07:12:24
【问题描述】:

我有一个需要迭代的 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
    }]
}

数据中的键并不总是相同的(我刚刚使用了示例,有 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
    }
}

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

【问题讨论】:

    标签: json asynchronous node.js foreach


    【解决方案1】:

    有点晚了,但我相信下面会给出进一步的说明。

    您也可以使用简单的循环遍历 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】:

      我最喜欢的方式是,

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

      【讨论】:

      • 感谢您的帮助,我知道这个问题已经过时了,但我有很多时间在寻找解决方案,而您的解决方案对我有好处,只是效果很好我将属性添加到 var objValue = yourJsonObj [objKey ] .properties @Tharanga
      【解决方案3】:

      如果我们使用 nodeJS,我们绝对应该利用它提供的不同库。 underscoreJS 中的 each()、map()、reduce() 等内置函数减少了我们的工作量。这是一个示例

          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)          
                 })
            })
      

      【讨论】:

        【解决方案4】:

        看看 Traverse。它将递归地为您遍历对象树,并且在每个节点上,您都有许多可以访问的不同对象 - 当前节点的键、当前节点的值、当前节点的父节点、当前节点的完整键路径等。@987654321 @。我已经使用它对我想要清理循环引用的对象以及当我需要在转换各种数据位时进行深度克隆时产生了良好的效果。下面是从他们的示例中提取的一些代码,让您了解它的功能。

        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);
        

        【讨论】:

          【解决方案5】:

          不确定它是否有帮助,但似乎在此处托管的节点中可能有一个用于异步迭代的库:

          https://github.com/caolan/async

          Async 是一个实用模块,它为使用异步 JavaScript 提供了直接、强大的功能。虽然最初是为与 node.js 一起使用而设计的,但它也可以直接在浏览器中使用。

          Async 提供了大约 20 个函数,其中包括常见的“功能性”可疑函数(map、reduce、filter、forEach…)以及一些常见的异步控制流模式(并行、系列、瀑布…)。所有这些函数都假定您遵循 node.js 约定,即提供单个回调作为异步函数的最后一个参数。

          【讨论】:

            【解决方案6】:

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

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

            【讨论】:

            • 我也更喜欢 Object.keys 方法...对您的建议进行了小改进,但如果您执行反向 for 循环,它会更快一些。当然仅适用于迭代顺序无关紧要的情况!尽管从技术上讲,返回对象键的顺序没有保证的顺序,但它可能是一个静音点,顺序会很重要;)jsperf.com/forward-vs-reverse-for-loop [code] var keys = Object.keys(obj); for (i = keys.length; i--;) { obj[keys[i]]; } [/code]
            • 最好使用 let 而不是 var:for( let i = 0; length = keys.length; i
            【解决方案7】:

            您可能还想在循环中使用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 密集型工作,您将需要生成一个 child process 来完成该工作或使用 web workers

            【讨论】:

            • hasOwnProperty 似乎很有趣,我可能会将其合并到循环中。循环内的工作不是那么密集。只需将给定的值添加到数据库即可。所需要的只是对 SQL 进行一些格式化。
            【解决方案8】:

            如果你想避免阻塞,这只是非常大的循环所必需的,那么将循环的内容包装在一个函数中,如下所示:process.nextTick(function(){&lt;contents of loop&gt;}),这将推迟执行直到下一个滴答声,从而有机会待处理的来自其他异步函数的调用。

            【讨论】:

              【解决方案9】:

              您可以通过这种方式遍历 JavaScript 对象:

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

              myobject 可能是你的 json.data

              【讨论】:

              • 这个行为是否异步?
              • 不,不是,但我不知道为什么它应该是异步的。 Node.js 真的很快。如果您的对象中有数千个键,我会理解,但不是 20 个;)
              • 我明白你的意思了!目前对我来说这一切都很新,所以只想保持最佳实践! :)
              • 嗨!只是想知道,出于好奇,如果有数千个密钥,我们该怎么办?意识到这篇文章很老了。
              • 在 2021 年 10 月完美工作。
              猜你喜欢
              • 1970-01-01
              • 2013-05-18
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2015-10-11
              • 2023-01-03
              • 2017-12-11
              • 2021-11-03
              相关资源
              最近更新 更多