Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript reflection: Get nested objects path

In this stackoverflow thread, i learnt you can get a object path via a simple string.

Accessing nested JavaScript objects with string key

consider the following:

var person = { name: "somename", personal: { weight: "150", color: "dark" }};

var personWeight = deep_value(person,"personal.weight");

I an trying to construct an array of the object values who are not of type 'object' from my 'person' object.

Hence the array would look like:

[['name', []],['personal.weight', []],['personal.color', []]];

I want them to look in that form because i have further use for it down the road.

That's what I've tried:

var toIterate = { name: "somename", personal: { age: "19", color: "dark" } }

var myArray = [];

$.each(toIterate, recursive);

function recursive(key, value) {         

    if (key !== null) {
        myArray.push([key, []]);
    }
    else {
        $.each(value, recursive);
    }
}

console.log(myArray);
like image 950
TotalWar Avatar asked Aug 21 '15 13:08

TotalWar


2 Answers

Just use recursion to walk the object.

var person = {
    name: "somename",
    personal: {
        weight: "150",
        color: "dark",
        foo: {
            bar: 'bar',
            baz: 'baz'
        },
        empty: {
        }
    }
};

// however you want to do this
var isobject = function(x){
    return Object.prototype.toString.call(x) === '[object Object]';
};

var getkeys = function(obj, prefix){
    var keys = Object.keys(obj);
    prefix = prefix ? prefix + '.' : '';
    return keys.reduce(function(result, key){
        if(isobject(obj[key])){
            result = result.concat(getkeys(obj[key], prefix + key));
        }else{
            result.push(prefix + key);
        }
        return result;
    }, []);
};

var keys = getkeys(person);

document.body.innerHTML = '<pre>' + JSON.stringify(keys) + '</pre>';

Then use Array.prototype.map to massage the array of keys into your preferred format. Note the behaviour with person.personal.empty.

This does seem like a strange way to store an object's keys. I wonder what your 'further use for it down the road' is.

like image 198
1983 Avatar answered Oct 16 '22 18:10

1983


This is what worked for me. Note that, a raw map is created first and then mapped to an join the items in the Array with ..

var toIterate = {
  name: "somename",
  personal: {
    age: "19",
    color: "dark"
  }
};

console.log(getObjPath(toIterate).map(item => item.join('.')));

function isObject(x) {
  return Object.prototype.toString.call(x) === '[object Object]';
};

function getObjPath(obj, pathArray, busArray) {
  pathArray = pathArray ? pathArray : [];
  if (isObject(obj)) {
    for (key in obj) {
      if (obj.hasOwnProperty(key)) {
        if (isObject(obj[key])) {
          busArray = busArray ? bussArray : [];
          busArray.push(key);
          getObjPath(obj[key], pathArray, busArray);
        } else {
          if (busArray) {
            pathArray.push(busArray.concat([key]));
          } else {
            pathArray.push([key]);
          }
        }
      }
    }
  }
  return pathArray;
}

Good Luck...

like image 29
Aakash Avatar answered Oct 16 '22 17:10

Aakash