简体   繁体   中英

JSON nested object versus Javascript array

In my web app I have an object which is built from a JSON string passed from a server. A typical JSON string might look like this:

{
  "_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...

There might be thousands of objects in the JSON string. I can happily parse the JSON using JSON.parse(). This creates an object that I can iterate over using the following javascript:

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

This seems rather inefficient. I'd rather do this:

doSomething(itemlist[soughtKey]);

But presumably to do this I'd need to convert my top-level object into some sort of key-indexable array? I assume there is no way to gain access to specific itemlist items using their id values?

Assuming not, what is the most efficient way to convert my top-level itemlist object into an array of objects where all the properties of the original items are still accessible via the dot notation, and any item can be directly accessed via its id? (I know each nested item will have an _id, but I won't know the rest of the structure in advance). And are there any performance trade-offs between converting the JSON object to the array versus leaving it as-is and using my inefficient loop?

Thanks very much.

In order to locate something by value you have to loop over the object and test the values at the individual keys. There's no way to avoid this.

In order to build a lookup object you have to loop over the entire object one time and collect values from the first object and store them in the second object. This is intensive up front, but will equate to savings later if you have to repeatedly find things by the values you'd like to use as keys.

So the question is, do you do this once (you're after a specific piece of the JSON return) or does this happen repeatedly in your page (you use part of the object in section A of the code, then another part of the object in section B, etc)? If the former, it's probably not worth the added overhead to loop through the entire object and create a lookup. If the latter, then you'll probably benefit in the long run by creating an easier way to retrieve your desired information by appropriate keys.

Creating your lookup object might go something like this:

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']
  };
}

You could give linq.js ( reference ) a try, if you want.

Yes, it's yet another library to load, but it can make your life very easy afterwards with things like this.

var soughtKey = '4x3tC1oTBkyvbu43rQj0EQ==' ;

Enumerable.From(myJsonObject)
          .Where('$._id.$binary == "' + soughtKey + '"')
          .ForEach(doSomething);

function doSomething(obj) {
  // do something with "obj";
}

See it working in this jsFiddle .


To create an look-up object, indexed by ID, would be a one-liner as well:

var index = Enumerable.From(myJsonObject).ToObject("$._id.$binary", "$");

// later:
doSomething(index[soughtKey]);

Try something like http://goessner.net/articles/JsonPath/ . XPath for JSON.

Try record each item with its id?

var remember = {};

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM