Search multiple elements by key inside multiple json structures - javascript

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?

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:
const file1 = {
"name":"First file",
"randomName3874":{
"items":[
{
"name":"item1"
}
]
},
"items":[
{
"name":"randomItem2"
}
]
}
const file2 = {
"name":"Another file",
"randomName00000":{
"nestedItems":{
"items":[
{
"name":"item87"
}
]
}
},
"stuff":{
"items":[
{
"name":"randomItem35"
}
]
}
}
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()
})
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:
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()
}
// test:
const file1 = {
"name":"First file",
"randomName3874":{
"items":[
{
"name":"item1"
}
]
},
"items":[
{
"name":"randomItem2"
}
]
}
const file2 = {
"name":"Another file",
"randomName00000":{
"nestedItems":{
"items":[
{
"name":"item87"
}
]
}
},
"stuff":{
"items":[
{
"name":"randomItem35"
}
]
}
}
console.log(
{ data: extractKey([file1, file2], 'items') }
)

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);

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])

Related

Spread Operator for array of array

How to perform spread opration on salesuser array object. need to add ..salesuserstargetAmount:500, in that object
{
"station": [
{
"stationname":"chennai",
"stationtargetAmount":500,
"salesusers":[
{
" salesusersname":"tester",
},
]
},
{
"stationname":"chennai22222",
"stationtargetAmount":500,
"salesusers":[
{
" salesusersname":"tester222222",
},
]
}
]
}
Tried with
let salesusertargetamt = "100"
this.setState({
salesusers: this.state.station.map((items) => {
items.salesusers.map(el => (el.salesusersname !== "" ? { ...el, salesusertargetamt } : el))
});
Curly braces ({) are tricky here because they both mean block of code and JavaScript object so you need to wrap them with ():
let salesusertargetamt = "100";
let obj = {
"station": [
{
"stationname":"chennai",
"stationtargetAmount":500,
"salesusers":[
{
" salesusersname":"tester",
},
]
},
{
"stationname":"chennai22222",
"stationtargetAmount":500,
"salesusers":[
{
" salesusersname":"tester222222",
},
]
}
]
};
let result = obj.station.map(items => ({
...items,
salesusers: items.salesusers.map(user => (user.salesusersname !== "" ? {...user, salesusertargetamt} : user ))
}))
console.log(result);
let salesusertargetamt = "100"
this.setState({
salesusers: this.state.station.map((items) => {
return items.salesusers.map(el => (el.salesusersname !== "" ? { ...el, stationtargetAmount: salesusertargetamt } : el))
});

How to iterate nested object keys with child nested

I want to iterate the nested object keys which will be have inner child nested as well:
Nested object code:
{
"F2C3C496-BEA6-A5E8-15F0-E2867304B463": {
"D39FD497-9529-6CC3-70DE-E8D9277C18D3": {
"child": {
"87A1817D-CFA9-70FD-131B-224658AF13CE": {
"next": {
"F7A90266-B7F4-4CC2-0F1B-D4B320E2EC1A": {}
}
}
},
"next": {
"B49927ED-369E-E219-FC1A-8E4BAAFC3933": {
"next": {}
}
}
}
}
}
JS code to iterate:
flowThrough = (obj, callback, context?, path?: string) => {
let nestedKey=';'
Object.keys(obj).forEach(key => {
if(!isEmptyObject(key))
callback(key, context, path);
if (!isEmpty(obj[key]) && typeof obj[key] === 'object') {
if(obj[key].hasOwnProperty('next'))
nestedKey = obj[key].next;
else if(obj[key].hasOwnProperty('child'))
nestedKey = obj[key].child;
else nestedKey = obj[key];
this.flowThrough(nestedKey, callback, context, (path)? has(context, path.concat(".next"))?path.concat(`.next[${get(context, path.concat(".next").length)}]`): path.concat('.').concat("next[0]") : key)
}
})
}
Actually, the above code working for one nested level to get key(ids). If it reaches the empty object key then the loop is ending there. actually, it should check any other child/next is there or not.
Expected output:
{ "flow": [
{
"id": "F2C3C496-BEA6-A5E8-15F0-E2867304B463",
"next": [
{
"id": "D39FD497-9529-6CC3-70DE-E8D9277C18D3",
"child": [
{
"id": "87A1817D-CFA9-70FD-131B-224658AF13CE",
"next": [
{
"id": "F7A90266-B7F4-4CC2-0F1B-D4B320E2EC1A",
"next": []
}
]
}
],
"next": [
{
"id": "B49927ED-369E-E219-FC1A-8E4BAAFC3933",
"next": []
}
]
}
]
}
]
}
Please give me the solution for this.
let obj = {
"F2C3C496-BEA6-A5E8-15F0-E2867304B463": {
"D39FD497-9529-6CC3-70DE-E8D9277C18D3": {
"child": {
"87A1817D-CFA9-70FD-131B-224658AF13CE": {
"next": {
"F7A90266-B7F4-4CC2-0F1B-D4B320E2EC1A": {}
}
}
},
"next": {
"B49927ED-369E-E219-FC1A-8E4BAAFC3933": {
"next": {}
}
}
}
}
}
const setObj = e => {
let tmp = {}
if (Array.isArray(e[0])) e = e[0]
if (typeof e[0] === 'string' && e[0].split('-').length === 5) {
tmp = {
id: e[0],
next: setObj(Object.entries(e[1]))
};
} else if (e[1]) {
tmp = {
child: setObj(Object.entries(e[1]))
};
}
return tmp
}
let newobj = Object.entries(obj).map(setObj)[0]
console.log(newobj)
Original answer...
Here's one way to go about it. Use a recursive function along with Object.entries to gather the data. I found that the result was a series of nested arrays of id's - so I flattened them all with join() and then split them again. Finally, filter() helped remove the empty array indexes
let obj = {
"F2C3C496-BEA6-A5E8-15F0-E2867304B463": {
"D39FD497-9529-6CC3-70DE-E8D9277C18D3": {
"child": {
"87A1817D-CFA9-70FD-131B-224658AF13CE": {
"next": {
"F7A90266-B7F4-4CC2-0F1B-D4B320E2EC1A": {}
}
}
},
"next": {
"B49927ED-369E-E219-FC1A-8E4BAAFC3933": {
"next": {}
}
}
}
}
}
const getKeys = e => {
let ret = []
if (e[0].split('-').length === 5) ret.push(e[0]);
if (e[1]) ret.push(Object.entries(e[1]).map(getKeys))
return ret.join(',')
}
let keys = Object.entries(obj).map(getKeys)[0].split(",").filter(e => e)
console.log(keys)

how to change the nest array object key and same array in javascript

I have two arrays of an object obj and editObj I am trying the change the inner array key value from obj array-based on editObj.
const obj= [
{
"id":"cmate",
"permissions":[
{
"name":"audioFeature",
"description":"sample description",
"options":[{"name":"Yes","value":"Y"}, {"name":"No","value":"N"}, {"name":"Veiw","value":"V"}],
},
{
"name":"documentFeature",
"description":"sample description",
"options":[{"name":"Yes","value":"Y"},{"name":"No","value":"N"}],
}
]
},
{
"id":"Vmate",
"permissions":[
{
"name":"audioFeature",
"description":"sample description",
"options":[{ "name":"Yes", "value":"Y"},{"name":"No", "value":"N"}],
},
{
"name":"videoFeature",
"description":"sample description",
"options":[{ "name":"Yes", "value":"Y"},{"name":"No","value":"N"}],
}
]
}
] ;
const editObj = [
{
"id":"cmate",
"attributes":[
{
"name":"audioFeature",
"value":["Y",N"],
"disabled":true
},
{
"name":"documentFeature",
"value":["N"],
"disabled":false
}
]
},
{
"id":"Vmate",
"attributes":[
{
"name":"audioFeature",
"value":["Y","N"],
"disabled":false
},
{
"name":"videoFeature",
"value":["Y","N"],
"disabled":true
}
]
}
]
I had tried with this code but I stuck in a certain time I try to return the resultArr but it's not working for me.
obj.map(el => {
editObj.map(elm => {
if (el.applicationId === elm.applicationId) {
el.permissions.map(p => {
elm.attributes.map(a => {
if(p.name === a.name) {
console.log(el)
const resultArr = el.permissions.map((item, index) => {
let res = { ... item };
res.options = item.options.filter(option => elm[0].attributes[index].value.includes(option.value));
return res;
});
console.log(resultArr)
}
})
})
}
})
})
my expected output should be
[
{
"id":"cmate",
"permissions":[
{
"name":"audioFeature",
"description":"sample description",
"options":[{"name":"Yes","value":"Y"}, {"name":"No","value":"N"}],
"disabled":true
},
{
"name":"documentFeature",
"description":"sample description",
"options":[{"name":"No","value":"N"}],
"disabled":false
}
]
},
{
"id":"Vmate",
"permissions":[
{
"name":"audioFeature",
"description":"sample description",
"options":[{ "name":"Yes", "value":"Y"},{"name":"No", "value":"N"}],
"disabled":false
},
{
"name":"videoFeature",
"description":"sample description",
"options":[{ "name":"Yes", "value":"Y"},{"name":"No","value":"N"}],
"disabled":true
}
]
}
]
Try this piece of code, it will take obj and editObj and return the output in outputObj.
const outputObj = [];
obj.forEach(el => {
editObj.forEach(elm => {
if (el.id === elm.id) {
let tempObj = {
id: el.id,
permissions:[]
}
el.permissions.forEach(p => {
elm.attributes.forEach(a => {
if (p.name === a.name) {
const rObj = {
name: p.name,
description: p.description,
disabled: a.disabled,
options: p.options.filter(option => {
if(a.value.includes(option.value)) {
return option
}
})
}
tempObj.permissions.push(rObj)
}
})
})
outputObj.push(tempObj);
}
})
})
I changed your code a little bit and it start showing something:
You need to explicitly return from arrow function.
console.log(obj.map(el => {
return editObj.map(elm => {
if (el.id === elm.id) {
return el.permissions.map(p => {
return elm.attributes.map(a => {
if(p.name === a.name) {
return resultArr = el.permissions.map((item, index) => {
let res = { ... item };
res.options = item.options.filter(option => elm.attributes[index].value.includes(option.value));
return res;
});
}
})
})
}
})
}));
Checkout an interesting article to understand your mistake:
https://dev.to/samanthaming/es6-arrow-functions-cheatsheet-1cn#:~:text=With%20normal%20functions%2C%20if%20you,return%20keyword%20can%20be%20skipped.

how to change value of all nodes of json array

I have a json array with different key values and need to add a ServerUrl to the beginning of all node values using a loop without writing multiple statements to do that by using javascript:
"Urls": [
{ "getCar": "/getAllCars" },
{ "getPerson": "/getAllPersons" },
{ "getBook": "/getAllBooks" }
],
"ServerUrl": "http://192.168.1.1:3000"
The expected result must be:
"Urls": [
{ "getCar": "http://192.168.1.1:3000/getAllCars" },
{ "getPerson": "http://192.168.1.1:3000/getAllPersons" },
{ "getBook": "http://192.168.1.1:3000/getAllBooks" }
],
Any advice would be appreciated.
You can use map to map your objects to new objects. Those objects have a single property, which you can get with Object.keys. The new object can get that same property name using the computed property name feature:
var obj = {
"Urls": [
{ "getCar": "/getAllCars" },
{ "getPerson": "/getAllPersons" },
{ "getBook": "/getAllBooks" }
],
"ServerUrl": "http://192.168.1.1:3000"
};
var urls = obj.Urls.map(o => Object.keys(o).map(k => ({ [k]: obj.ServerUrl + o[k] }))[0]);
console.log(urls);
const jsonVal = {
"Urls": [
{ "getCar": "/getAllCars" },
{ "getPerson": "/getAllPersons" },
{ "getBook": "/getAllBooks" }
],
"ServerUrl": "http://192.168.1.1:3000"
}
const result = jsonVal.Urls.map(val =>
Object.keys(val).reduce((resultObj, endpointKey) => {
resultObj[endpointKey] = `${jsonVal.ServerUrl}${val[endpointKey]}`;
return resultObj;
}, {})
);
Try (where your data are in d)
d.Urls.forEach( (x,i,a,k=Object.keys(x)[0]) => x[k] = d.ServerUrl + x[k]);
let d = {
"Urls": [
{ "getCar": "/GetAllGroupCustomers" },
{ "getPerson": "/getAllItems" },
{ "getBook": "/GetAllCustomers" }
],
"ServerUrl": "http://192.168.1.1:3000"
}
d.Urls.forEach( (x,i,a,k=Object.keys(x)[0]) => x[k] = d.ServerUrl + x[k]);
console.log(d);
A version that modifies your own object
var obj = {
"Urls": [
{ "getCar": "/getAllCars" },
{ "getPerson": "/getAllPersons" },
{ "getBook": "/getAllBooks" }
],
"ServerUrl": "http://192.168.1.1:3000"
};
obj.Urls.forEach(o => o[Object.keys(o)[0]] = `${obj.ServerUrl}${o[Object.keys(o)[0]]}`);
console.log(obj);

Javascript: Find key and its value in JSON

I have a JSON object that is returned in different ways, but always has key. How can I get it?
E.g.
"Records": {
"key": "112"
}
Or
"Records": {
"test": {
"key": "512"
}
}
Or even in array:
"Records": {
"test": {
"test2": [
{
"key": "334"
}
]
}
}
Tried several options, but still can't figure out (
I will not write the code for you but give you an idea may be it will help, First convert JSON object in to string using
JSON.stringify(obj);
after that search for Key using indexOf() method.
Extract previous '{' and Next '}' string and again cast in to JSON object.
using
var obj = JSON.parse(string);
Then
var value = obj.key
I think this migth be solution (asuming key is always string and you don't care about res of data)
const data = [`"Records": {
"test": {
"test2": [
{
"key": "334",
"key": "3343"
}
]
}
}`, `"Records": {
"test": {
"key": "512"
}
}`, `"Records": {
"key": "112"
}`]
const getKeys = data => {
const keys = []
const regex = /"key"\s*:\s*"(.*)"/g
let temp
while(temp = regex.exec(data)){
keys.push(temp[1])
}
return keys
}
for(let json of data){
console.log(getKeys(json))
}
How can i get it?
Recursively! e.g.
function getKey(rec) {
if (rec.key) return rec.key;
return getKey(rec[Object.keys(rec)[0]]);
}
https://jsfiddle.net/su42h2et/
You could use an iterative and recursive approach for getting the object with key in it.
function getKeyReference(object) {
function f(o) {
if (!o || typeof o !== 'object') {
return;
}
if ('key' in o) {
reference = o;
return true;
}
Object.keys(o).some(function (k) {
return f(o[k]);
});
}
var reference;
f(object);
return reference;
}
var o1 = { Records: { key: "112" } },
o2 = { Records: { test: { key: "512" } } },
o3 = { Records: { test: { test2: [{ key: "334" }] } } };
console.log(getKeyReference(o1));
console.log(getKeyReference(o2));
console.log(getKeyReference(o3));
You can try this
const data = {
"Records": {
"key": "112"
}
};
const data2 = {
"Records": {
"test": { "key": "512" }
}
};
const data3 = {
"Records": {
"test": {
"test2": [
{ "key": "334" },
]
}
}
};
function searchKey(obj, key = 'key') {
return Object.keys(obj).reduce((finalObj, objKey) => {
if (objKey !== key) {
return searchKey(obj[objKey]);
} else {
return finalObj = obj[objKey];
}
}, [])
}
const result = searchKey(data);
const result2 = searchKey(data2);
const result3 = searchKey(data3);
console.log(result);
console.log(result2);
console.log(result3);

Categories

Resources