【问题标题】:JSON nested object versus Javascript arrayJSON 嵌套对象与 Javascript 数组
【发布时间】:2011-12-02 10:55:45
【问题描述】:

在我的网络应用程序中,我有一个对象,它是从服务器传递的 JSON 字符串构建的。典型的 JSON 字符串可能如下所示:

{
  "_id": {
    "$binary": "4x3tC1oTBkyvbu43rQj0EQ==",
    "$type": "03"
  },
  "title": "Sony FW31 Lit 973.pdf",
  "tags": [
    {
      "category": "Machine",
      "text": "Cold Planers"
    },
    {
      "category": "Attachments",
      "text": "Blades"
    }
  ]
}
,
{
  "_id": {
    "$binary": "s/Svg2CjSUWB1QGJ7e3QeA==",
    "$type": "03"
  },
  "title": "Sony FW31 Lit 974.pdf",
  "tags": [
    {
      "category": "Machine",
      "text": "Cold Planers"
    },
    {
      "category": "Attachments",
      "text": "Blades"
    }
  ]
},... and lots more items...

JSON 字符串中可能有数千个对象。我可以使用 JSON.parse() 愉快地解析 JSON。这将创建一个对象,我可以使用以下 javascript 对其进行迭代:

var soughtKey='4x3tC1oTBkyvbu43rQj0EQ==';
for (var ii = 0; ii < itemlist.length; ii++) {
    var item = itemlist[ii];
    if (item._id$binary==soughtKey){
        doSomething(item);
    }
}

这似乎相当低效。我宁愿这样做:

doSomething(itemlist[soughtKey]);

但大概要做到这一点,我需要将我的顶级对象转换为某种键索引数组?我认为没有办法使用它们的 id 值来访问特定的 itemlist 项目?

假设不是,将我的顶级 itemlist 对象转换为对象数组的最有效方法是什么,其中原始项目的所有属性仍然可以通过点符号访问,并且任何项目都可以通过其直接访问ID? (我知道每个嵌套项都会有一个_id,但我不会提前知道结构的其余部分)。在将 JSON 对象转换为数组与保持原样和使用我的低效循环之间是否存在任何性能权衡?

非常感谢。

【问题讨论】:

    标签: javascript arrays performance json parsing


    【解决方案1】:

    如果你愿意,你可以试试linq.js (reference)。

    是的,它是另一个要加载的库,但它可以让你之后的生活变得非常轻松。

    var soughtKey = '4x3tC1oTBkyvbu43rQj0EQ==' ;
    
    Enumerable.From(myJsonObject)
              .Where('$._id.$binary == "' + soughtKey + '"')
              .ForEach(doSomething);
    
    function doSomething(obj) {
      // do something with "obj";
    }
    

    在this jsFiddle 中查看它。


    要创建一个按 ID 索引的查找对象,也是单行的:

    var index = Enumerable.From(myJsonObject).ToObject("$._id.$binary", "$");
    
    // later:
    doSomething(index[soughtKey]);
    

    【讨论】:

      【解决方案2】:

      为了按值定位某些内容,您必须遍历对象并测试各个键的值。没有办法避免这种情况。

      为了构建一个查找对象,您必须遍历整个对象一次并从第一个对象收集值并将它们存储在第二个对象中。这在前期很密集,但如果您必须通过您想用作键的值反复查找内容,则相当于以后节省。

      所以问题是,你是这样做一次(你在 JSON 返回的特定部分之后)还是在你的页面中重复发生这种情况(你在代码的 A 部分中使用对象的一部分,然后是另一个B 部分中的对象的一部分等)?如果是前者,那么循环整个对象并创建查找可能不值得增加开销。如果是后者,那么从长远来看,您可能会受益于创建一种更简单的方法来通过适当的键检索所​​需信息。

      创建查找对象可能如下所示:

      var byIds = {};
      
      for (var ii = 0, l = items.length; ii < l; ++ii) {
        var item = items[ii];
      
        byIds[item._id.$binary] = {
          'title': item['title'],
          'tags': item['tags']
        };
      }
      

      【讨论】:

      • 我会经常进行查找,所以昂贵的前期任务是值得的。我正在考虑构建第二个对象,以便它包含第一个对象中的所有嵌套对象,但数组可以通过 _id 值(作为关联数组)进行索引。好听吗?
      • @Journeyman - 是的,这听起来很对。我发布的演示代码正是这样做的。之后,您将能够执行byIds[soughtKey] 之类的操作,它会返回一个包含该 ID 的标题和标签的对象。
      • 另外值得一试的是 TaffyDB。它允许您查询 JSON 集合。这是非常漂亮的IMO。 taffydb.com
      【解决方案3】:

      尝试用它的 id 记录每个项目?

      var remember = {};
      
      for (var ii = 0; ii < itemlist.length; ii++) {
          var item = itemlist[ii];
          remember[item._id.$binary] = item;
      }
      

      【讨论】:

      • 大概一旦我构建了这个,查找起来会比我的原始代码快得多?
      • 如果你需要通过 id 获得相同的物品两次或更多,这是值得的。
      【解决方案4】:

      试试http://goessner.net/articles/JsonPath/。 JSON 的 XPath。

      【讨论】:

        猜你喜欢
        • 2014-09-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-08-11
        • 2021-07-19
        • 2013-09-29
        • 2017-02-14
        相关资源
        最近更新 更多