7

Let me explain in detail. I have below an object with me -

{
    "OBJECT1" : {
        "NAME1" : "VALUE1",
        "NAME2" : "VALUE2",
        "NAME3" : "VALUE3"
     },
     "OBJECT2" : {
        "NAME4" : "VALUE4",
        "NAME5" : "VALUE5"
     }
}

From this object, I want to get something like number of elements in OBJECT1 = 3 and number of elements in OBJECT2 = 2. If at all this is possible using javascript. Basically what I am trying to do is, to loop through the name value pairs available in the object dynamically so that if someone adds another element to object, I don't have to change my code.

Also any alternative is also ruled out since I am allowed to only use object in my use-case.

Marcel Korpel
  • 21,536
  • 6
  • 60
  • 80
Sachin Shanbhag
  • 54,530
  • 11
  • 89
  • 103
  • possible duplicate of [Length of Javascript Associative Array](http://stackoverflow.com/questions/5223/length-of-javascript-associative-array) – kennytm Aug 20 '10 at 09:13
  • 2
    Those objects are not called JSON objects. JSON is only a notation, that represents *JavaScript* objects. – Marcel Korpel Aug 20 '10 at 10:15
  • 1
    @Marcel Korpel: so, is it possible to say that such JSON string as we see here is a serialized form of a JS object? – Piskvor left the building Aug 21 '10 at 06:39
  • @Korpel - Yeah, even I am curious to know answer for Piskvor's question. Coz in our project, we store such objects in a ".json" file and do a fileparse to get the object in our javascript source code. Hence I thought these were called JSON objects. – Sachin Shanbhag Aug 21 '10 at 15:36
  • 1
    @Piskvor and Sachin: Correct. There is no such thing as a ‘JSON object’. When those JSON strings are parsed, they are ‘interpreted’ to generate a true (native) JavaScript object (remember JSON is an abbreviation of ‘JavaScript Object Notation’). That's also why I deleted the [json] tag: the question *is* about a JavaScript object, which is showed to us in JSON format (which is completely sound, BTW). – Marcel Korpel Aug 22 '10 at 12:59
  • @Korpel - Thank you very much for this helpful insight, this is like getting 2 answers in one shot ;) – Sachin Shanbhag Aug 22 '10 at 14:44
  • Just one more thing: you're ‘calling’ me by my surname, but that doesn't notify me. Please read [How do comment replies work?](http://meta.stackexchange.com/questions/43019/how-do-comment-replies-work) to see how to do this correctly. – Marcel Korpel Aug 22 '10 at 19:34

3 Answers3

9

Without converting your object you could iterate through the object counting properties like so:

function countObjectProperties(obj)
{
    var count = 0;
    for(var i in obj)
        if(obj.hasOwnProperty(i))
            count++;

    return count;
}

Expanding on why you need to use hasOwnProperty as I said in the comment below you can run into an issue where a library or browser has added methods and properties to Objects, in order to avoid counting these we check for hasOwnProperty before counting it. More details at MSDN or at Mozilla Developer Center

Kristoffer Sall-Storgaard
  • 10,576
  • 5
  • 36
  • 46
4

For JSON string that represent an object (which is your case), you cannot use any length property. you need to loop through the object (see Kristoffer S Hansen's answer).

If it represented an array, you could get the length with:

var len = arr.length;

JQuery makes it simpler:

var len = $(JSON).length;
KeatsPeeks
  • 19,126
  • 5
  • 52
  • 83
  • 2
    No Jquery please and also I am supposed to avoid eval in my project standards. – Sachin Shanbhag Aug 20 '10 at 09:12
  • eval was for the array example, which you don't need anyway. It was just additional information :) Ok I've removed eval since it's off-topic. – KeatsPeeks Aug 20 '10 at 09:17
  • Don’t use `eval` if not necessary. – Gumbo Aug 20 '10 at 09:18
  • Currently, my JSON object is just NAME VALUE pairs as in the example above. I am not sure if looping thru all elements in object is possible or not. just in case its not possible, then maybe I need to move NAME VALUE pairs into an array from where I can use the length and loop through. – Sachin Shanbhag Aug 20 '10 at 09:24
1

To answer your broader goal, as specified in your question:

For looping through the properties, you can use the for..in construct:

for (var item in myobject) {
  // some browsers add more properties to every object, we don't want those
  if (myobject.hasOwnProperty(item)) {
    do_something(item);
  }
}

Assuming that myobject is the object in your question, this will loop through it and call do_something(OBJECT1) and do_something(OBJECT2); you can use the same construct to loop through the child objects:

// loop through OBJECT1 and OBJECT2
for (var item in myobject) {
  // some browsers add more properties to every object, we don't want those
  if (myobject.hasOwnProperty(item)) {
    // loop through the item's children
    for (var pair in item) {
      if (item.hasOwnProperty(pair)) {
        // each of the name:value pairs will be passed to this
        do_something_else(item,pair);
      }
    }
  }
}
Piskvor left the building
  • 91,498
  • 46
  • 177
  • 222
  • In the second snippet it seems that `item` is already the *key* of each key-value pair, so it makes no sense to iterate over it again... – Timwi Aug 20 '10 at 16:29
  • @Timwi: Actually, no: in the outer loop, we iterate over the top-level properties, i.e. OBJECT1 and OBJECT2. In the inner loop, we iterate over *their* properties, i.e. NAME1,NAME2,NAME3, and NAME4, NAME5, respectively. If the nesting went further, we could be iterating over the deeper objects (maybe recursion could be used). – Piskvor left the building Aug 20 '10 at 16:47
  • To clarify, in the second loop I'm iterating the properties of a property of the top-level object (`myobject.OBJECT1.NAME1` etc). This nesting could go deeper, but doesn't in this case. – Piskvor left the building Aug 20 '10 at 16:59
  • Yeah, sorry, for some reason I thought your second snippet was the `do_something` function the first one called inside the loop. Never mind :) – Timwi Aug 20 '10 at 17:23