0

I am trying to figure out how do I get the all the values in a JSON object a aparticular level from the top level. I do know how to iterate through all the objects in the following way:

for (var key in dirTree) {
    if(dirTree.hasOwnProperty(key)) {
      var val = dirTree[key];
      console.log(JSON.stringify(val));
    }
  }

But how do I do that for getting at a particular level from the top?

user1692342
  • 5,007
  • 11
  • 69
  • 128

2 Answers2

0

By recursing down the properties of an object you could do it. In this case, my sample isn't very expressive, it won't tell you if it didn't find a property in your path, it will just return undefined for unknown paths, but it will give back whatever the last property contains (as in my sample, it should return 'text')

ofcourse, this sample doesn't make any sense if the string is static, but if it's coming from user input or from a value you are receiving outside of your control, you could use it, otherwise you could ofcourse simply start with jsonObject.complex.english.title ;)

'use strict;';

var jsonObject = {
  complex: {
    english: {
      title: 'text'
    }
  }
};

/*
 * @method getPath
 *
 * @param obj Object for which a path must be found
 * @param path String value indicating the path that will be traversed, joined with .
 *
 * @returns undefined or the object that was found at the specified path
 */
function getPath(obj, path) {
  var arrayPath, 
      propertyName,
      nextPath;
  console.log('getting path "' + path + '" for', obj);
  if (!obj) {
    // previous evaluation returned null, empty string, false, or undefined
    return;
  }
  if (!path) {
    // no path given, or path is empty string
    return obj;
  }
  arrayPath = path.split('.');
  propertyName = arrayPath[0];
  if (!propertyName) {
    // invalid path, return the current object
    return;
  }
  if (arrayPath.length === 1) {
    // no deeper searching required, return the value or undefined in case this object doesn't have the property
    return obj[propertyName];
  }
  // reassemble the left over string
  nextPath = arrayPath.slice(1, arrayPath.length).join('.');
  // search the next part of the path
  return getPath(obj[propertyName], nextPath);
}

function displayResults(inputSelector, outputSelector) {
  var inputEl = document.querySelectorAll(inputSelector)[0],
      outputEl = document.querySelectorAll(outputSelector)[0];
  
  if (inputEl && outputEl) {
    outputEl.innerHTML = JSON.stringify(getPath(jsonObject, inputEl.value));
  }
  // no submit ;)
  return false;
}

displayResults('#pathField', '#output');
<form onsubmit="return displayResults('#pathField', '#output');">
  <label for="pathField">Enter the path to find in the object</label>
  <input type="text" required pattern="[\w.|\w]*" id="pathField">
  <button type="submit">Find and output path</button>
</form>
<div id="output"></div>
Icepickle
  • 12,689
  • 3
  • 34
  • 48
0

Yes, Icepickle is right. Recursion is the best way to handle this. Here is a solution:

var testObj = {
  "one": {
    "1": {"msg": "msg1"},
    "2": {"msg": "msg2"},
    "3": {"msg": "msg3"}
  },
  "two": {
    "1": {"msg": "msg4"},
    "2": {"msg": "msg5"},
    "3": {"msg": "msg6"}
  }
};
function follow(obj, n){
  if (n == 1) {
    return Object.keys(obj).map(function(k){
      return obj[k];
    });
  }
  else return Object.keys(obj).map(function(k){
    return follow(obj[k], n-1);
  });
}
console.log(follow(testObj, 2));

http://jsbin.com/boqekunaba/edit?js,console,output

As written, this will return the second level of the example JSON tree. You can change n to 3 to see what happens. The results are arrays to keep this concise. This is the result of using the map method, which is a shortcut for writing a for loop. If we simply want objects, we'll have to tweak this code a little more.

mikkelrd
  • 413
  • 2
  • 10