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/

2
  • 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'. Commented Sep 24, 2014 at 7:16
  • Just a quick note - `jsonStr' is not JSON, it's a JavaScript object. Commented Sep 24, 2014 at 7:46

2 Answers 2

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?

Sign up to request clarification or add additional context in comments.

3 Comments

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
If thats the case I would use no. 4. Defiant.js
I have added an example how to search your concrete structure using Defiant.js
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"}}]}}};

4 Comments

@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.
Kindly take a look this fiddle , i have regenerated the hierarchy and its not working now jsfiddle.net/ma3kno2o/4
@AdilWaqar I made a better hierarchy (for a few folders in a folder) and wrote a script for it - jsfiddle.net/ma3kno2o/5
@AdilWaqar This is for your current variant - jsfiddle.net/ma3kno2o/8 Sorry, I have to sleep )

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.