0

I have a json object which looks like this:

var testJ = {"ROOT":{
        dir : 'app',
        files : [
            'index.html',
            {
                dir : 'php',
                files: [
                    'a.php',
                    {
                        dir : 'extras',
                        files : [
                            'a.js',
                            'b.js'
                        ]
                    }
                ]
            }
        ]
    }};

I need to extract all the files and append into an array (index.html,a.php,a.js..etc)

For this I wrote a javascript code as follows:

var arr=[];
    function scan(obj,append)
    {
        var k;
        if (obj instanceof Object) {
            for (k in obj){
                if (obj.hasOwnProperty(k)){
                    if(k=='files')
                    {
                      scan( obj[k],1 );  
                    }


                }                
        }
    } else {
        body += 'found value : ' + obj + '<br/>';
        if(append == 1)
        arr.push(obj);

        alert("Arr"+ arr);
    };

};

scan(testJ,0);

I am not able to figure out where am I going wrong. Could some give me pointers?

user1692342
  • 5,007
  • 11
  • 69
  • 128

2 Answers2

1
var res = [];
function gather(j) {
  for (var k in j) {
    if (k === 'files') {
      addFiles(j[k]);
    } else if (typeof j[k] === 'object') {
      gather(j[k]);
    }
  }
}
function addFiles(f) {
  for (var i = 0; i < f.length; i++) {
    if (typeof f[i] === "string") {
      body += 'found value : ' + obj + '<br/>';
      res.push(f[i]);
    } else {
      gather(f[i]);
    }
  }
}
gather(testJ);

Free tips:

instanceof is some cancerous stuff. Why does instanceof return false for some literals?

Always, always use === for comparison, not ==

I also wouldn't blindly use hasOwnProperty unless you're afraid the thing you're operating on might have a modified prototype, https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in just for simplicity.

Community
  • 1
  • 1
bbill
  • 2,264
  • 1
  • 22
  • 28
  • I missed out a ROOT at the start in the JSON object (which I have updated). Your snippet does not work in that case. – user1692342 Jun 09 '15 at 21:57
  • 1
    Please, copy and paste responsibly ;P I don't really want to help you do that. https://jsfiddle.net/w6qo3nk3/. I – bbill Jun 09 '15 at 21:58
  • 1
    I've also updated the JSFiddle and code so you don't have to even worry about the root element – bbill Jun 09 '15 at 22:03
  • 1
    Thanks for your help! I always learn new things by posting a question on SO! – user1692342 Jun 09 '15 at 22:08
  • ICould you suggest a way to find all the files under a particular directory? – user1692342 Jun 09 '15 at 22:40
  • Simplest way is to add a check that `j['dir'] === "dirname"` before the line that says `addFiles(j[k]);`. Please either make a new question or state all your requests upfront in the future :) makes things much easier. – bbill Jun 10 '15 at 15:31
1

How about a map reduce approach?:

function mapJ(subject) {
  return subject.files.map(function(item) {
    if (typeof item === "string") {
      return item;
    } else {
      return parseJ(item);
    }
  });
}

function reduceJ(subject) {
  return subject.reduce(function(prev, cur) {
    return prev.concat(cur);
  }, []);
}

function parseJ(subject) {
  return reduceJ(mapJ(subject));
}

var result = parseJ(testJ));
Stephen
  • 621
  • 5
  • 14