Recursive function in JavaScript for parsing intricate JSON object or array

I received a JSON response that looks like this:

{
   "data":[
      {
         "type":"node--base_product_coffee",
         "id":"6dbb5a52-13ea-4f74-8af9-eb9e3ba45918",
         "date":"1990",
         "data1":[
            {
               "type1":"product_coffee1",
               "id1":"6dbb5a52-13ea-4f74-8af9-eb9e3ba45777",
               " date1 ":[
                  {
                     "  res ":"  oui "
                  },
                  {
                     "  res ":"  non "
                  }
               ]
            },
            {
               "type1":"product_coffee2",
               "id1":"6dbb5a52-13ea-4f74-8af9-eb9e3ba45666",
               "date1":[
                  {
                     "  res ":"  ouiii "
                  },
                  {
                     "  res ":"  nonnn "
                  }
               ]
            }
         ]
      }
   ]
}

My objective is to extract values from a dynamic path such as data.data1.date1.res in order to retrieve the result ['oui', 'non', 'ouiii', 'nonnn']

To achieve this, I have created the following function:

parseIt = function(response, s) {
    if (!response) return null;
    if (!s) return obj;

    var data = Array.isArray(response) ? JSON.parse(JSON.stringify(response)) : JSON.parse(response);
    var result = [];
    var path = s.split('.');

    if (Array.isArray(data)) {
        for (var i = 0; i < data.length; i++) {
            if (getType(data[i][path[0]]) == 'string') {
                result.push(data[i][path[0]]);
            } else {
                parseIt(data[i][path[i]], path.slice(1).join('.'));
            }
        }
    } else {
        for (var p in data) {
            if (getType(data[p]) == 'string') {
                result.push(data[p]);
            } else {
                parseIt(data[p], path.slice(1).join('.'));
            }
        }
    }

    document.writeln('result=>' + result + '</br>');
    return result;
}

document.writeln(parseIt(response2, 'data.data1.date1.res')+'</br>');

//Console Output
result=>oui,non
result=>
result=>
result=>

However, I am encountering two issues:

  1. I am only getting results for the elements of date1.res ('oui' and 'non'), but I need all its elements ('oui', 'non', 'ouiii', 'nonnn')
  2. The result array is empty (how can I store results in a list when using recursion)

Your assistance is greatly appreciated, as I require this functionality for my work with complex JSON data.

Answer №1

To achieve this functionality, you can use recursive function calls along with array flattening.

const testData={"data":[{"type":"node--base_product_coffee","id":"6dbb5a52-13ea-4f74-8af9-eb9e3ba45918","date":"1990","data1":[{"type1":"product_coffee1","id1":"6dbb5a52-13ea-4f74-8af9-eb9e3ba45777","date1":[{"res":"oui"},{"res":"non"}]},{"type1":"product_coffee2","id1":"6dbb5a52-13ea-4f74-8af9-eb9e3ba45666","date1":[{"res":"ouiii"},{"res":"nonnn"}]}]}]};
 

parseData = function(data, [key, ...path]) {
    return (Array.isArray(data) ? data : [data]).reduce((acc, obj) => {
        if (path.length) {
            acc.push(parseData(obj[key], path));
        } else if (obj[key]) {
            acc.push(obj[key]);
        }
        return acc;
    }, []).flat();
}

function retrieveValue(response, s) {
    if (!response) return null;
    if (!s) return obj;
    var path = s.split('.');
    return parseData(response, path).flat();
}

console.log(retrieveValue(testData, 'data.data1.date1.res'))

Answer №2

I believe there may be a more efficient solution,

const options = {
    "selection":[
       {
          "category":"node--base_item_coffee",
          "identifier":"6dbb5a52-13ea-4f74-8af9-eb9e3ba45918",
          "year":"1991",
          "details":[
             {
                "subCategory":"item_coffee1",
                "identity":"6dbb5a52-13ea-4f74-8af9-eb9e3ba45777",
                "times":[
                   {
                      "response":"yes"
                   },
                   {
                      "response":"no"
                   }
                ]
             },
             {
                "subCategory":"item_coffee2",
                "identity":"6dbb5a52-13ea-4f74-8af9-eb9e3ba45666",
                "times":[
                   {
                      "response":"yesss"
                   },
                   {
                      "response":"nopppeee"
                   }
                ]
             }
          ]
       }
    ]
 }
 

 for(const element of options.selection){
    for(const element2 of element.details){
        for(const element3 of element2.times){
            console.log(element3.response)
        }
    }
}

However, you are also capable of achieving similar results using this approach.

Answer №3

To retrieve the desired values, iterate through data.data1 using a loop.

const result = data.map(element => {
    // console.log(element)
    return element.data1.map(element => {
        // console.log(element)
        return element.date1.map(element => {
            // console.log(element)
            return element.results;
        });
    });
}).join().split(",");

console.log(result)

This should yield ["oui", "non", "ouiii", "nonnn"] with the log statements in place for convenience.

Answer №4

A recent revision has brought attention to this question. I believe there is a simpler way to accomplish this task.

Below is the code implementation:

const makeArray = (x) => x ? Array.isArray(x) ? x : [x] : []

const _flatPath = ([p, ...ps]) => (o) =>
  p ? makeArray(o[p]).flatMap(_flatPath(ps)): makeArray(o)

const flatPath = (path = '') => _flatPath(path.split('.'))

const input = {data: [{type: "node--base_product_coffee", id: "6dbb5a52-13ea-4f74-8af9-eb9e3ba45918", date: "1990", data1: [{type1: "product_coffee1", id1: "6dbb5a52-13ea-4f74-8af9-eb9e3ba45777", date1: [{res: "oui"}, {res: "non"}]}, {type1: "product_coffee2", id1: "6dbb5a52-13ea-4f74-8af9-eb9e3ba45666", date1: [{res: "ouiii"}, {res: "nonnn"}]}]}]}

console.log(
  flatPath('data.data1.date1.res')(input)
)

makeArray function basically converts values into arrays. It checks if the value is already an array, and if not, it wraps it in one. If the value is nil, it returns an empty array.

The main function, _flatPath, navigates through the object based on the supplied path as an array of strings, flattening the results into a single array.

flatPath serves as the interface for splitting a string like 'data.data1.date1.res' into an array

['data', 'data1', 'date1', 'res']
to feed into _flatPath.


Please note that I assumed the extra spaces around keys and values in the input provided were unintentional errors. If you have keys such as ' res ', but intend to locate them with 'res', additional modifications would be necessary.

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

TreeSet's Comparator fails to eliminate duplicate numbers

I created my own custom comparator to initialize a TreeSet as a min-heap. Everything works well when removing duplicates of small numbers like 1, 2, and 3. However, I noticed that when dealing with large numbers, duplicates are not removed as expected. Her ...

Is there a way to extract variables from a MySQL database and integrate them into a JavaScript function?

Hello everyone, I am looking to add markers on a map. In order to do this, I need to extract longitude and latitude from a database table. 1- I have used JavaScript to display the map (Google Maps). var map; var initialize; initialize = function( ...

Is it possible to convert a string using object-to-object syntax?

After running a particular function, I received the following results: [ "users[0].name is invalid", "date is invalid", "address.ZIP is invalid" ] I am looking for a way to convert this output from object syntax i ...

Storing class variables in a specified order as an array in Python

I wrote a basic Python code snippet class Person: name = "" surname = "" age = "" def __init__(self): arr = #I'm looking for a way to potentially store these in ['name', 'surname', 'age&apos ...

What is the method for setting required to true only when the user meets a specific condition?

Hello, I am creating models for my mongodb. I want the birthday field to be required only if the user being added is a student. If the user is a teacher, it is okay if no birthday is provided. const userSchema = mongoose.Schema({ 20 21 _id: m ...

Remove the array element if the value is blank

I have an array with different objects, and I need to efficiently delete the entries where the name is empty, similar to the first and third object in the example below: var myArray = [ { "Name": "", "Value": "" }, { "Name": "aaa", "Value": "bbb" ...

I am facing an issue with Recharts not occupying the full width in my Nextjs/Reactjs project. Despite setting it to 100% width, it does not behave as

I am currently working with Recharts in combination with Next.js and Tailwindcss. I decided to create my own barchart by copying a code snippet from Recharts, but encountered an issue where changing the height to aspect worked fine, however setting the wid ...

React | Rendering a single object from an array nested within another object

Consider the following data structure: const data = [ { title: 'title', description: 'description' images: [ { mainImg: 'url' }, { img1: 'url' }, { img2: 'url' }, { img3: 'url ...

Combining the power of AngularJS with the versatility of sails

A project I'm working on involves utilizing sails.js for back-end and AngularJS for front-end. My plan is to use the Yeoman-angular generator https://github.com/yeoman/generator-angular to create the Angular app first. Once the front-end development i ...

Ways to fix: Encountering an Unexpected token < in JSON at position 0

Hey there! I've just started dipping my toes into the MEAN stack. I'm currently using Angular to connect to an api.js file, which in turn connects to my mongodb database. However, I've come across this error: ERROR SyntaxError: Unexpected t ...

Why isn't the tooltip function functioning properly in Bootstrap 5 beta1 when using an SVG image?

Currently, I am utilizing Bootstrap 5 beta1. However, I have encountered an issue. When I use a tooltip with a button, it works fine. But if I use a tooltip with an icon (svg, feather icon), it doesn't work. In other instances, when I use a tooltip ...

Guide to initiating requests using a button in React-query

Struggling to grasp React-query, I've hit a roadblock in triggering requests using the onSubmit event. Currently, the code is defaulting to sending a request with "washington" as the parameter and displaying it on the screen. Additionally, a new reque ...

Get rid of any unnecessary class on the element

I'm currently working on an image slider that displays before and after images when the user drags left to right. The issue I'm facing is that the 'draggable' class is being added not only to these images but also to my hero images. It ...

The Vue Watch feature fails to trigger when incorporating axios

Hello everyone, I am facing an issue with my code that involves fetching data from a database using axios. The problem is that the watch function is not triggering in the .then() block. Below is the snippet of code I am currently working with. Thank you ...

Ensuring proper JSON string formatting in XCode by parsing NSStrings

I have encountered a situation where I am extracting data from a PLIST file to create a JSON string for Facebook Connect integration. NSString *eventLink = [eventDictionary objectForKey:EVENT_FIND_OUT_MORE_KEY]; NSString *eventLinkEscaped = [eventLink str ...

Converting SQL database information into a JSON array

Greetings, I recently followed a tutorial to create a database, which can be found at this link: https://www.digitalocean.com/community/tutorials/a-basic-mysql-tutorial My goal is to convert my SQL database into a JSON array, similar to the format shown b ...

Obtaining a JSON string from a URL in Xamarin.Forms PCL

For instance, I encountered an issue with retrieving a JSON string from the following URL: . Since WebClient is not supported in Xamarin.forms PCL, I turned to Xamarin's documentation on utilizing web services in forms and followed their example. Li ...

Extracting strings from JSON data in BigQuery

Is there a way to use REGEX_EXTRACT to pull out the value NPR from a string? {'Id': None, 'Name': 'NPR'} I have attempted various approaches but none seem to be compatible with bigquery. Here is what I have tried so far: RE ...

Utilizing fullpage.js for seamless class addition and removal on the top portion of a webpage

I've encountered an issue with fullpage.js (https://github.com/alvarotrigo/fullPage.js/) on my website http://vatuvara.com/. Essentially, I am trying to add a class of 'black-nav' to #masthead if the visitor is not in the first section of t ...

AngularJs FileList Drag and Drop Feature

Being brand new to front-end development, I decided it would be a fun challenge to implement drag and drop functionality on an existing upload page. However, as I began integrating ng-flow (a directive that helps with drag and drop), I encountered difficul ...