Reputation: 85
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:
I need your help, because I need this in my work in which we have complex JSON like this.
Upvotes: 1
Views: 1685
Reputation: 50807
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.
Upvotes: 0
Reputation: 2205
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'))
Upvotes: 2
Reputation: 1298
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...
Upvotes: 0
Reputation: 834
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.
Upvotes: 0