4

I have the following object

{
"locations": {
    "Base 1": {
        "title": "This is base 1",
        "Suburb 1": {
            "title": "Suburb 1 in Base 1",
            "Area A": {
                "title": "Title for Area A",
                "Street S1": {
                    "title": "Street S1 title"
                },
                "Street C4": {
                    "title": "Street C4 title"
                },
                "Street B7": {
                    "title": "Street B7 title"
                }
            },
            "Another Area": {
                "title": "Title for Area A",
                "Street S1": {
                    "title": "Street S1 title"
                },
                "Street C4": {
                    "title": "Street C4 title"
                },
                "Street B7": {
                    "title": "Street B7 title"
                }
            }
        },
        "Another Suburb": {
            "title": "Suburb 1 in Base 1",
            "Area A": {
                "title": "Title for Area A",
                "Street S1": {
                    "title": "Street S1 title"
                },
                "Street C4": {
                    "title": "Street C4 title"
                },
                "Street B7": {
                    "title": "Street B7 title"
                }
            },
            "Another Area": {
                "title": "Title for Area A",
                "Street S1": {
                    "title": "Street S1 title"
                },
                "Street C4": {
                    "title": "Street C4 title"
                },
                "Street B7": {
                    "title": "Street B7 title"
                }
            }
        }
    },
    "Base2": {}
}
}

I'm given arrays to fetch "titles" from the "locations" object and each array can be different. I know I can access individual values like so :

locations["Base 1"]["title"]
locations["Base 1"]["Another Suburb"]["title"]
locations["Base 1"]["Another Suburb"]["Area A"]["title"]
etc etc.

But I'm not sure how to get the value of title if I'm given arrays like so :

AnArray = ["Base 1", "title"];
AnArray = ["Base 1", "Another Suburb", "title"];
AnArray = ["Base 1", "Another Suburb", "Area A", "title"];
AnArray = ["Base 1", "Another Suburb", "Another Area", "title"];

Is there a way to parse / work with these arrays so each returns the correct title value from the locations object?

I have to fetch the value of the title in each case, and I'm not even sure where to start. I tried joining the array and then fetching the 'title' values but that didn't seem to work.

Noob here, so please don't mind if the question sounds stupid / or makes no sense.

So the question is, how do I fetch values from a hierarchical object when the references are in an array ?

Norman
  • 705
  • 1
  • 10
  • 24
  • **Wow** has this been asked and answered. [Here](http://stackoverflow.com/questions/11922383/i-have-a-nested-data-structure-json-how-can-i-access-a-specific-value), for instance, and [here](http://stackoverflow.com/questions/15719604/object-object-or-undefined-returned-while-accessing-json-elements/15719624#15719624). – T.J. Crowder Apr 02 '13 at 07:47
  • What you've shown isn't a valid object or array definition, so it's hard to help you, as the details of how you get to the object depend quite a bit on the **actual** structure of it. If you have this in memory, you should be able to use the development tools that are built into your browser to show it in a valid format, then copy and paste that here. – T.J. Crowder Apr 02 '13 at 07:49
  • What kind of arrays are those? I can't understand how or why are you given the top locations array in such manner... so you say you are given 4 Array objects instead of one? – Azurlake Apr 02 '13 at 07:54
  • Thank you for the references T.J ... I just updated the question with a valid JSON object. – Norman Apr 02 '13 at 07:55
  • @Azurlake - I'm given arrays to query the title in each case (for each array) the query should return the correct title from the locations object. The arrays in the question are for example only. – Norman Apr 02 '13 at 07:57

3 Answers3

2
function getNested(obj, ar_keys) {
    var innerObj = obj;
    for(var i=0,il=ar_keys.length; i<il; i++){
      innerObj = innerObj[ar_keys[i]];
    }
    return innerObj;
}

You would call it with

 getNested(x['locations'], ar_keys);

where x is your object and ar_keys is the array of keys.

Riccardo Galli
  • 12,419
  • 6
  • 64
  • 62
  • For some reason the JSON validator stripped the spaces ... I updated the question to fix that. Thanks for the solution :) – Norman Apr 03 '13 at 11:45
0

I suppose you need something like that:

  • iterate through every array
  • iterate through the values of the array
  • for each value nest one level deeper into the object
  • store the final values in an array

Try this:

var arrays = [
    ["Base 1", "title"],
    ["Base 1", "Another Suburb", "title"],
    ["Base 1", "Another Suburb", "Area A", "title"],
    ["Base 1", "Another Suburb", "Another Area", "title"]
],
array, i, j,
obj = {
    "locations": {
        "Base1": {
            "title": "Thisisbase1",
            "Suburb1": {
                "title": "Suburb1inBase1",
                "AreaA": {
                    "title": "TitleforAreaA",
                    "StreetS1": {
                        "title": "StreetS1title"
                    },
                    "StreetC4": {
                        "title": "StreetC4title"
                    },
                    "StreetB7": {
                        "title": "StreetB7title"
                    }
                },
                "AnotherArea": {
                    "title": "TitleforAreaA",
                    "StreetS1": {
                        "title": "StreetS1title"
                    },
                    "StreetC4": {
                        "title": "StreetC4title"
                    },
                    "StreetB7": {
                        "title": "StreetB7title"
                    }
                }
            },
            "AnotherSuburb": {
                "title": "Suburb1inBase1",
                "AreaA": {
                    "title": "TitleforAreaA",
                    "StreetS1": {
                        "title": "StreetS1title"
                    },
                    "StreetC4": {
                        "title": "StreetC4title"
                    },
                    "StreetB7": {
                        "title": "StreetB7title"
                    }
                },
                "AnotherArea": {
                    "title": "TitleforAreaA",
                    "StreetS1": {
                        "title": "StreetS1title"
                    },
                    "StreetC4": {
                        "title": "StreetC4title"
                    },
                    "StreetB7": {
                        "title": "StreetB7title"
                    }
                }
            }
        },
        "Base2": {}
    }
},
current, key,
result = [];

for (i = 0; i < arrays.length; i++) {
    array = arrays[i];

    // reset current to the locations object
    current = obj.locations;

    for (j = 0; j < array.length; j++) {

        // remove spaces from the keys
        key = array[j].replace(' ', '', 'gi');

        if (current[key]) {
            // if there is such key then nest further
            current = current[key];
        } else {
            // there is no such key - log it
            console.log(key);
        }
    }

    if (typeof current === "string") {
        // if you have reached a string with the nesting add it to the result
        result.push(current);
    }
}

// output the final result
console.log(result);

In my case it outputs:

["Thisisbase1", "Suburb1inBase1", "TitleforAreaA", "TitleforAreaA"]

I have added additional logging so it is clear if something with the keys goes wrong.

Haralan Dobrev
  • 7,617
  • 2
  • 48
  • 66
-1

If the arrays are 'paths' to the required title you could do it this way.

Note that 'locations' is required in this case as it's the start of the path and title is not required since we're always looking for it.

var path = ["locations", "Base1", "AnotherSuburb"];

(function search(o, a){
    for(var p in o){
        if(typeof o[p] === 'object' && path.indexOf(p) !== -1){
            a.push(p);
            if(a.join('') === path.join('')){
                // match, print the title
                console.log(o[p].title);
            }
            else{
               search(o[p], a);
            }
        }
    }
})(object, []);

Will print Suburb1inBase1

Demo: http://jsfiddle.net/louisbros/Fq63D/

louisbros
  • 865
  • 5
  • 10
  • Nice recursion, but you iterate through each property in the object. You can use the `hasOwnProperty` method or you can actually not iterate through the object properties at all. Also the OP has spaces in the array values. – Haralan Dobrev Apr 02 '13 at 10:01