Exploring JSON data in JavaScript

In my Json data, I have a nested structure of folders and files. My goal is to determine the number of files in a specific folder and its sub-folders based on the folder's ID. Below is an example of the JSON dataset:

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"
                    }]
                }
            }
        }
    }
};

Each folder has a unique name and ID. If I want to find the number of files within a specific folder and its subfolders by searching with its ID, for instance, if I input the folder "name 123" and ID "1411538469568", it should display only 2 files:

"C22-1(EU仕様)_20140923162409.xlsx"
and
"Machine_Inspection_20140923162329.xlsx"
. However, if I provide the folder name "Root" and ID "Root," it should retrieve all file IDs.

I am currently working on this functionality in a JSFiddle: http://jsfiddle.net/ma3kno2o/

Answer №1

If you're looking to enhance your search capabilities, consider using Defiant.js

Have a look at this Fiddle for a specific search scenario where you can extract file IDs from the element with ID: root and Name: root:. I've used Defiant.js in this demonstration:

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

When compared to custom search methods mentioned before, Defiant.js stands out as it simplifies the process of fetching file IDs with just one line of code:

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

This approach minimizes errors when dealing with dynamic data. Defiant.js makes use of XPath expressions for searching. Explore more about it here:

Here are some alternative options worth considering:

  1. You can utilize plain JQuery for your searches

    How to search JSON tree with jQuery

  2. Another option is JsonPath, similar to XPath but tailored for JSON files. It enables queries such as:

    $..folder.file
    

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

    https://github.com/s3u/JSONPath

  3. Consider exploring Json-Query which introduces its own language designed for deep queries. For example:

    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 none of these options resonate with you, there are plenty more alternatives available: Is there a query language for JSON?

Answer №2

This solution may not be the most elegant (apologies, it's 4am), but it tackles the problem through recursion. Your existing structure does not easily cater to same-level folders, so I made some adjustments and provided the corresponding code: 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 initial code needed modifications for your new requirements.

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"}}]}}};

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Discovering the Essence of AngularJS Test Runner: Unraveling the

I recently started learning Angular JS and decided to follow the tutorial here. I've encountered a roadblock in step 8 where I need to write a test to check if the thumbnail images are being displayed. The concept behind it is simple. There is a JSON ...

Comparing prevProps and this.props in React Native Redux: What is the most effective method?

Does anyone know how to efficiently handle triggering a function in my React Native app only when a specific prop has changed? This is the current implementation I have: componentDidUpdate(prevProps) { if (prevProps.a !== this.props.a) { <trigger ...

What is the typical output value that fluctuates?

I only have one input to work with. My goal is to set the input value to "5", then display "3" in the "total" field and "4" in the "total2" field. Additionally, for every increment of +1 to the input value, I want the "total" and "total2" fields to also in ...

Incorporating <span> elements into a comma-separated list using Jquery on every other item

When I receive a comma-separated list of items from a database and insert them into a table cell, I want to apply alternating styles to make it easier for users to distinguish between them. For example: foo, bar, mon, key, base, ball I'm looking to ...

Explanation on retrieving JSON data from a ListView and passing it to another activity using SQLite in Android Studio

My goal is to navigate from the HOMESCREEN to a new activity, INTERNETSEARCHSCREEN, and then finally to the EDITINGSCREEN. I have successfully displayed JSON data on a listview but now I want to select a movie from the listview and display specific fields ...

retrieving attribute values from JSON objects using JavaScript

I am struggling to extract certain attribute values from a JSON output and use them as input for a function in JavaScript. I need assistance with this task! Below is the JSON data that I want to work with, specifically aiming to extract the filename valu ...

Attempting to implement usedispatch hook in combination with userefs, however, encountering issues with functionality

I've been exploring the Redux useDispatch hook lately. I created a simple app for taking notes in a todo list format. However, I am facing an issue with useDispatch as it's not working for me and I keep encountering this error: Module build faile ...

"Unexpected compatibility issues arise when using TypeScript with React, causing errors in props functionality

Just the other day, my TypeScript+React project was running smoothly. But now, without making any changes to the configurations, everything seems to be broken. Even rolling back to previous versions using Git or reinstalling packages with NPM does not solv ...

Generate text in a random spot effortlessly

After doing some research on various development platforms, I stumbled upon this JSFiddle that seems to have a solution for my requirements. The only thing missing is the ability to input a specific word (without user input) and automate the process at fix ...

How can I effectively refresh the provider_token / access token for Discord in NextJS with Supabase Auth?

Currently, I have encountered an issue with my NextJs project using Supabase Auth for authentication. I am currently utilizing the Discord provider and everything works fine initially. However, after a few minutes, the session object gets updated and the p ...

What is the method to ensure an element is displayed in Selenium WebDriver?

Looking for assistance on how to choose options from a dropdown when the element is not visible and has a boolean attribute? Here's the HTML code snippet: <select id="visualizationId" style="width: 120px; display: none;" name="visualization"> & ...

What is the optimal method for storing extracted JSON data?

One question on my mind is how to effectively store JSON data. I have a JSON file that I parse using JSON Library and now I have the data from the file. However, I want to be able to store this data for future use. I'm seeking advice on the best way ...

Can't access innerText in Firefox

This is the code snippet I'm having trouble with: <div id="code">My program<br />It is here!</div> <script type="text/javascript"> var program=document.getElementById('code'); ShowLMCButton(program.innerText); </s ...

How to adjust cell alignment in Handsontable

Handsontable showcases cell alignment options in the align cell demo: Horizontal Left Center Right Justify Vertical Top Middle Bottom Displayed below is a screenshot: To retrieve data, utilize the following code snippet: $('#table-wrapper&ap ...

The UseEffect hook continues to run even if the dependency (router.query) remains the same

useEffect(() => { console.log('applying filter'); const updatedFilters = { status: { values: { label: router.query.status, value: router.query.status }, }, // Add additional filter properties here... }; ...

Angular ng-if directive contains a specific class

I am trying to create a directive that will only be active when an element has a specific class. I have tried the following code: <feedback-analytics ng-if="$('#analyticTab').hasClass('active')"></feedback-analytics> Unfor ...

What steps should be taken to guarantee that the filter function is completed before making an Axios request, in order to avoid encountering an undefined variable error when working with Axios

Encountering an issue with an undefined variable while trying to stringify and parse a filtered array in the backend using axios. The error occurs sporadically on the live server, often triggered by a timeout function within the filter process. This resul ...

"Implementing a column template in jqgrid post-creation: A step-by-step

Can't apply column template with Free jqgrid once it's been created. I've attempted: var newOrderPriceTemplate = { align: "center", formatter: "showlink", formatoptions: { onClick: function() { alert('clicked&apos ...

React ensures that the page is not rerendered until after data has been fetched

I am dealing with the following code snippet. This is my React hook: const [isLoading, setIsLoading] = React.useState(true); useEffect(() => { setIsLoading(() => true); // I expect the page to rerender and display loading now. const select ...

Design a captivating Profile Picture form using HTML and CSS styling

In my form, I am looking to include a user's Profile picture which should be displayed in either a circular or rectangular shape. Initially, the image area will show a black background or a placeholder image. When the user clicks on this area, they sh ...