Craig552uk
Craig552uk

Reputation: 681

Finding values by Key in JSON

Given a de-serialized JSON object of arbitrary structure and mixed value types...

var data = {
  'a':'A1',
  'b':'B1',
  'c': [
    {'a':'A2', 'b':true}, 
    {'a':'A3', 'b': [1, 2, 3]}
  ]};

I'd like to return an array of values matching a given key.

> my_func(data, 'a')
['A1', 'A2', 'A3']

> my_func(data, 'b')
['B1', true, [1, 2, 3]]

The closest I've got is this, which gives the right result, but I think there's a better (faster/neater/more efficient) solution.

my_func = function(o,s,a){
    var a = a || [];
    if(o == null){
        return a;
    }
    if(s in o){
        a.push(o[s]);
    }
    for(e in o){
        if(typeof(o[e]) == "object"){
            a.concat(my_func(o[e], s, a))
        }
    }
    return a;
}

Any ideas?

Upvotes: 2

Views: 116

Answers (3)

Craig552uk
Craig552uk

Reputation: 681

Thank you all for your input. You've inspired me towards the following solution, which I'm much happier with.

walk_obj = function(o, fn){
    for(k in o){
        fn(k, o[k]);
        if(typeof(o[k]) == "object"){
            walk_obj(o[k], fn);
        }
    }
}

get_by_key = function(o, key){
    var a = [];
    walk_obj(o, function(k,v){
        if(k==key){
            a.push(v);
        }
    })
    return a;
}

Upvotes: 0

user663031
user663031

Reputation:

You can take advantage of the replacer parameter to JSON.stringify:

function my_func(data, prop) {
  var result = [];
  JSON.stringify(data, function(key, val) {
    if (key === prop) result.push(val);
    return val;
  });
  return result;
}

Upvotes: 0

Koen Peters
Koen Peters

Reputation: 12916

function traverse(obj,func, parent) {
  for (i in obj){
    func.apply(this,[i,obj[i],parent]);      
    if (obj[i] instanceof Object && !(obj[i] instanceof Array)) {
      traverse(obj[i],func, i);
    }
  }
}

function getPropertyRecursive(obj, property){
  var acc = [];
  traverse(obj, function(key, value, parent){
    if(key === property){
      acc.push({parent: parent, value: value});
    }
  });
  return acc;
}

call this like this

getPropertyRecursive( myobj, 'test' )

where myobj is the nested object and test is the key

Upvotes: 1

Related Questions