最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Javascript reflection: Get nested objects path - Stack Overflow

programmeradmin0浏览0评论

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);

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);
Share Improve this question edited May 23, 2017 at 12:08 CommunityBot 11 silver badge asked Aug 21, 2015 at 13:15 TotalWarTotalWar 3551 gold badge8 silver badges16 bronze badges 5
  • Why to pass the specific property personal.weight if your result will have all other properties? – DontVoteMeDown Commented Aug 21, 2015 at 13:22
  • im not sure what do you mean there. – TotalWar Commented Aug 21, 2015 at 13:29
  • If I got you right, you want a new func to produce that result, which has nothing to do with the func deep_value, actually? – DontVoteMeDown Commented Aug 21, 2015 at 13:35
  • that is correct.I would like a function to produce a string path representation of an object that i will feed to the deep_value function.I will post the answer that i figured out, its not very efficient mind you. – TotalWar Commented Aug 21, 2015 at 13:43
  • In fact, that is not correct. All what concerns to your question should in the main post, so as your code. I have added your code to your main qustion, you should remove that answer. – DontVoteMeDown Commented Aug 21, 2015 at 17:40
Add a comment  | 

4 Answers 4

Reset to default 11

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.

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...

I found the following solution on github.

https://github.com/mariocasciaro/object-path

I believe that the sole existence of the topic linked in the question is originated from string paths in dot notation.

However if in the first place you have to resolve all the paths then you can totally eliminate the string dot notation relieving yourself from unnecessary work.

Assuming that your schema is in the form of

const obj = { name: "somename", personal: { weight: "150", color: "dark" }};

then it would be ideal to collect the paths in an array like

const paths = [["name"], ["personal","weight"], ["personal","color"]]

so that obtaining any nested value is now a piece of cake. Like;

paths[1].reduce((value,path) => value[path], obj); // 150

Let's see in action.

function keyPaths(schema, ...keys){
  return Object.keys(schema)
               .reduce( (r,k) => ( typeof schema[k] === "object" ? r.push(...keyPaths(schema[k],...keys,k))
                                                                 : r.push([...keys,k])
                                 , r
                                 )
                      , []          
                      );                         
}

const obj    = { name: "somename", personal: { weight: "150", color: "dark" }},
      paths  = keyPaths(obj),
      result = paths[1].reduce((value,path) => value[path], obj);

console.log(JSON.stringify(paths,""));
console.log(result);

发布评论

评论列表(0)

  1. 暂无评论