0

I have a Json which have hierarchy of folders and files in it I am trying to get number of file in a folder and its sub-folders by a folder Id Here is the json

var jsonStr = {
    "hierarchy": {
        "date": "2014/09/24 15:21:23",
        "folder": {
            "name": "Root",
            "id": "Root",
            "file": [{
                "id": "22U2621210__PIN_検査報告書Ver1.0_20140923162232.xls"
            }, {
                "id": "C22-1(EU仕様)_20140923162409.xlsx"
            }, {
                "id": "Machine_Inspection_20140923162329.xlsx"
            }],
            "folder": {
                "name": "Level-1",
                "id": "1411396172645",
                "file": {
                    "id": "22U2621210__PIN_検査報告書Ver1.0_20140923162232.xls"
                },
                "folder": {
                    "name": "123",
                    "id": "1411538469568",
                    "file": [{
                        "id": "C22-1(EU仕様)_20140923162409.xlsx"
                    }, {
                        "id": "Machine_Inspection_20140923162329.xlsx"
                    }]
                }
            }
        }
    }
};

all the folders are with names and ids, if want to get number of files in that specific folder and its subfolders by searching with its id for example if I put folder name "123" and id "1411538469568" it should give me only 2 files which are "C22-1(EU仕様)_20140923162409.xlsx" and "Machine_Inspection_20140923162329.xlsx" but if i put folder name "Root" and Id= "Root" it should return me id's of all files

Here is the Fiddle on which i am working on http://jsfiddle.net/ma3kno2o/

AddyProg
  • 2,960
  • 13
  • 59
  • 110
  • Obviously, looping over all this would get you what you want. But that's not very efficient. I think you need a different structure so you can access `root` directly, and the subfolders on the same level but with reference to their 'parent'. – kasimir Sep 24 '14 at 07:16
  • Just a quick note - `jsonStr' is not JSON, it's a JavaScript object. – phuzi Sep 24 '14 at 07:46

2 Answers2

3

You can use Defiant.js

Here is a Fiddle for your concrete search scenario to pull the file IDs of the element with ID: root and Name: root:. I am using Defiant.js in this example:

http://jsfiddle.net/3z8mqr3u/1/

Defiant.js is superior to the custom search in the answer by @Cheery, to get the IDs of the files i had to use one line of code:

var ids = JSON.search(json,  "//*[name = 'Root' and id = 'Root']/file/id");

it is much less error-prone for searching dynamic data. Defiant.js uses XPath expressions. Check this link to learn more:

http://defiantjs.com/

Here are some other options:

  1. You can use plain JQuery

    How to search JSON tree with jQuery

  2. You can use JsonPath. It's like XPath for JSON files. You can do stuff like:

    $..folder.file
    

    http://goessner.net/articles/JsonPath/

    https://code.google.com/p/jsonpath/

    https://github.com/s3u/JSONPath

  3. You can use Json-Query. It has it-s own language for deep queries. e.g.:

    var data = { grouped_people: { 'friends': [ {name: 'Steve', country: 'NZ'}, {name: 'Bob', country: 'US'} ], 'enemies': [ {name: 'Evil Steve', country: 'AU'} ] } }

    jsonQuery('grouped_people[][country=NZ]', {data: data})
    

    https://github.com/mmckegg/json-query

If you dont like any of these here you can find more options: Is there a query language for JSON?

Community
  • 1
  • 1
Faris Zacina
  • 14,056
  • 7
  • 62
  • 75
  • Your answers contains excellent info but my problem is that i have a multilevel folder and sub folder hierarchy , I am never sure that I need to check on hierarchy.folder.file or hierarchy.folder.folder.file and so on this json is created dynamically and I am never sure of its levels – AddyProg Sep 24 '14 at 07:30
  • If thats the case I would use no. 4. Defiant.js – Faris Zacina Sep 24 '14 at 07:44
  • I have added an example how to search your concrete structure using Defiant.js – Faris Zacina Sep 24 '14 at 08:10
1

Not a nicest (sorry, 4am) solution, but the straight way through recursion.. Your structure does not support, in a normal way, same-level folders, so I reconfigured it, togerther with the code for it: http://jsfiddle.net/ma3kno2o/5/

function getFiles(id)
{
 var files = searchFolders(jsonStr.hierarchy.folders, false);
 alert('Found ' + files.length + " files\n" + JSON.stringify(files));

 function searchFolders(tree, count_files)
 {
    var data = [];     
    $.each(tree, function(key, val) {        
        var into = !count_files ? val.id == id : count_files;

        if (val.files && into)
            $.merge(data, getFiles(val.files));

        if (val.folders)
            $.merge(data, searchFolders(val.folders, into));                  

    });
    return data;
 }

 function getFiles(tree)
 { 
    var files = [];
    if (tree.id) return [tree.id]; 
    $.each(tree, function(key,val) {
       if (val.id)
          files.push(val.id);
    });
    return files;
 };
}


var jsonStr = {
    "hierarchy": {
        "date": "2014/09/24 15:21:23",
        "folders": [{
            "name": "Root",
            "id": "Root",
            "files": [{
                "id": "file.1"
            }, {
                "id": "file.2"
            }, {
                "id": "file.3"
            }],
            "folders": [{
                "name": "Level-1",
                "id": "1411396172645",
                "files": {
                    "id": "file.4"
                },
                "folders": [{
                    "name": "123",
                    "id": "1411538469568",
                    "files": [{
                        "id": "file.5"
                    }, {
                        "id": "file.6"
                    }]},
                    {
                    "name": "123",
                    "id": "1411538469569",
                    "files": [{
                        "id": "file.7"
                    }, {
                        "id": "file.8"
                    }]
                }]
            }]
        }]
    }
};

The old code will not work, so I rewrote it for your new varia

http://jsfiddle.net/ma3kno2o/8/

function getFiles(id)
{
 var stp = -1;
 var files = searchFolders(jsonStr.hierarchy, false);
 alert('Found ' + files.length + " files\n" + JSON.stringify(files));

 function searchFolders(tree, count_files)
 {
     var data = [];  
     var folders = tree.folder.length > 1 ? tree.folder : [tree.folder];
     $.each(folders, function(key, val) {  
        var into = !count_files ? val.id == id : count_files;

         if (val.file && into)
            $.merge(data, getFiles(val.file));

         if (val.folder)
            $.merge(data, searchFolders(val, into));  
    });
    return data;
 }

 function getFiles(tree)
 { 
    var files = [];
    if (tree.id) return [tree.id]; 
    $.each(tree, function(key,val) {
       if (val.id)
          files.push(val.id);
    });
    return files;
 };
}


var jsonStr= {"hierarchy":{"date":"2014/09/24 18:13:00","folder":{"name":"Root","id":"Root","file":[{"id":"file.1"},{"id":"file.2"},{"id":"file.3"}],"folder":[{"name":"Level-1","id":"1411396172645","file":{"id":"file.4"},"folder":{"name":"123","id":"1411538469568","file":[{"id":"file.5"},{"id":"file.6"}],"folder":{"name":"123-a","id":"1411549962260","file":{"id":"file.7"}}}},{"name":"level-2","id":"1411549976987","file":{"id":"file.8"}}]}}};
Cheery
  • 16,063
  • 42
  • 57
  • @AdilWaqar Your structure does not assume a few same-level folders inside of a one folder? Because 'folder' property does not have an array of folders. – Cheery Sep 24 '14 at 09:05
  • Kindly take a look this fiddle , i have regenerated the hierarchy and its not working now http://jsfiddle.net/ma3kno2o/4/ – AddyProg Sep 24 '14 at 09:18
  • @AdilWaqar I made a better hierarchy (for a few folders in a folder) and wrote a script for it - http://jsfiddle.net/ma3kno2o/5/ – Cheery Sep 24 '14 at 09:31
  • 1
    @AdilWaqar This is for your current variant - http://jsfiddle.net/ma3kno2o/8/ Sorry, I have to sleep ) – Cheery Sep 24 '14 at 10:23