1

I have a JSON response 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 goal is to able to get value as listfrom dynamic path like data.data1.date1.res to get the result ['oui', 'non', 'ouiii', 'nonnn']

So I started by this function

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


    if (Array.isArray(response)) {
        var data = JSON.parse(JSON.stringify(response));
    } else {
        var data = JSON.parse(response);
    }

    var result = [];
    var path = [];
    
    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=>

but I face two problems:

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

I need your help, because I need this in my work in which we have complex JSON like this.

1
  • Save yourself some serious time - use flat Commented Apr 13, 2021 at 2:08

4 Answers 4

2

You can try this by recursive function calls with array flattening.

const test={"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"}]}]}]};
 

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

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

console.log(getValue(test, 'data.data1.date1.res'))

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

Comments

0

I guess there is something better,

const test = {
    "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"
                   }
                ]
             }
          ]
       }
    ]
 }
 

 for(const obj of test.data){
    for(const obj2 of obj.data1){
        for(const obj3 of obj2.date1){
            console.log(obj3.res)
        }
    }
}

but yo can do something like this as well.

1 Comment

No the path to access the data should be dynamic, which means If I set a path it sould returns the list of all values from this path
0

You just need to loop through data.data1

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

console.log(res)

That should get you ["oui", "non", "ouiii", "nonnn"] left the .log's there so you don't have to type them yourself...

2 Comments

This is not dynamic path, you specify data and data1 and date1 and res litterally. I want that the path will dynamic, which means I give it a path like 'data.data1' or 'data.type' or whatever else as path it should return the list of all values that exists in that path.
You want it to return all res values?
0

A recent edit brought this question to the fore. I think this can be done much more simply.

Here's an 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 wraps up values in an array. If it's already an array, that's simply returned. If it's a scalar value, we return an array containing just that value. And if it nil, we return an empty array.

Our main function is _flatPath, which traverses the path (supplied as an array of strings) for the object, flattening the results into a single array.

And flatPath is the public facade to that, splitting a string like 'data.data1.date1.res' into the array ['data', 'data1', 'date1', 'res'] to pass to _flatPath.


Note that I made the assumption that the extra spaces wrapped around keys and values in the question's input were just typos. If you actually have keys that look like ' res ', but want to find them with 'res', then there's some more work to do.

Comments

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.