Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

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.

share|improve this question

4 Answers 4

up vote 3 down vote accepted

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']
  };
}
share|improve this answer
    
I will be running the lookup a lot, so the expensive up-front task is worth doing. I'm considering building the second object so it contains all the nested objects from the first, but where the array is indexable by the _id value ( as an associative array). Sound ok? –  Journeyman Oct 6 '11 at 17:45
    
@Journeyman - Yeah, that sounds about right. The demo code I posted does exactly that. Afterwards, you'd be able to do something like byIds[soughtKey] and it would return an Object that had the title and tags for that id. –  g.d.d.c Oct 6 '11 at 18:01
    
Also worth checking out, if you're so inclined, is TaffyDB. It allows you to query JSON Collections. It's pretty slick IMO. taffydb.com –  g.d.d.c Oct 6 '11 at 18:22

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]);
share|improve this answer
    
+1 for the linq.js. didnt know it exist ;) –  vhinn terrible Jul 11 '13 at 3:03

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

share|improve this answer

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;
}
share|improve this answer
    
presumably once I've built this it will be very much faster to lookup than my original code? –  Journeyman Oct 6 '11 at 17:46
    
if you need to get the same item by id twice or more, it's worth it. –  lostyzd Oct 6 '11 at 17:50

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.