I need to get the values of all the the arrays matching the items
key. I'm making a script in Javascript that needs to read the objects inside multiple items
arrays in multiple json files, but each json has a different structure. Example:
file1.json:
{
"name":"First file",
"randomName3874":{
"items":[
{
"name":"item1"
}
]
},
"items":[
{
"name":"randomItem2"
}
]
}
file2.json
{
"name":"Another file",
"randomName00000":{
"nestedItems":{
"items":[
{
"name":"item87"
}
]
}
},
"stuff":{
"items":[
{
"name":"randomItem35"
}
]
}
}
Desired result:
{
"data":[
{
"items":[
{
"name":"item1"
}
]
},
{
"items":[
{
"name":"randomItem2"
}
]
},
{
"items":[
{
"name":"item87"
}
]
},
{
"items":[
{
"name":"randomItem35"
}
]
}
]
}
In both files I want to extract the arrays that have the key items
. In the examples above the script should find 4 arrays. As you can see in both files each array is nested differently. How can I make this using Javascript?
CodePudding user response:
This will do it:
function omit(key, obj) {
const { [key]: omitted, ...rest } = obj;
return rest;
}
function getItems(obj) {
return (typeof obj === 'object'
? 'items' in obj
? [{ items: obj.items }].concat(getItems(omit('items', obj)))
: Object.values(obj).map(v => getItems(v))
: []
).flat()
}
console.log({
data: [file1, file2].map(o => getItems(o)).flat()
})
See it working:
Let's take it a step further and make it generic (work with an array of objects and extract any key) and provide it as a function, which you can use in other projects, as well:
function extractKey(objects, key) {
const omit = (key, obj) => {
const { [key]: omitted, ...rest } = obj;
return rest;
}
const getValues = (obj) => (typeof obj === 'object'
? key in obj
? [{ [key]: obj[key] }].concat(getValues(omit(key, obj)))
: Object.values(obj).map(o => getValues(o))
: []
).flat();
return objects.map(o => getValues(o)).flat()
}
// use:
extractKey([file1, file2], 'items');
See it working:
CodePudding user response:
Looping over like a tree-nested loop should do it.
let file1 = {
"name": "First file",
"randomName3874": {
"items": [
{
"name": "item1"
}
]
},
"items": [
{
"name": "randomItem2"
}
]
}
let file2 = {
"name": "Another file",
"randomName00000": {
"nestedItems": {
"items": [
{
"name": "item87"
}
]
}
},
"stuff": {
"items": [
{
"name": "randomItem35"
}
]
}
}
let itemsValues = [];
let desiredKey = 'items'
let loop = (value) => {
if (Array.isArray(value)) {
value.forEach(loop);
} else if (typeof value === 'object' && value !== null) {
Object.entries(value).forEach(([key, val]) => (key === desiredKey) ? itemsValues.push({ [desiredKey]: val }) : loop(val));
}
}
loop(file1);
loop(file2);
console.log(itemsValues);
CodePudding user response:
This should work:
function getIdInObjects(id, objects, output = { data: [] }) {
if (id in objects) output.data.push({[id]: objects[id]});
for (const key in objects) {
if (typeof(objects[key]) === 'object') getIdInObjects(id, objects[key], output);
}
return output;
}
console.log('items', [object1, object2])