How to iterate nested object keys with child nested - javascript

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)

Related

How to get the parent object value using child value

I have value "b" with me and I want to get the item "3648" using that how can I do that using JavaScript?
{
"someID": "16385421",
"items": {
"9836": {
"id": "a"
},
"3648": {
"id": "b"
},
"7738": {
"id": "c"
}
}
}
o/p
"3648": {
"id": "b"
}
Edited after your comment:
getByItemId = ( val ) => {
let result;
for( let elem in data.items ){
const check = data.items[ elem ];
if( check.id == val ) result = check;
}
console.log( result )
return result;
}
getByItemId( "b" )
You could do it with some code that resembled the following.
First we get all of the object keys in the obj.items object.
Next we iterate through them.
At each step, we check to see if the desired ID is contained within the sub-object indexed by the current key in the array. If it's found, we update the result object.
We then return an empty object if the key isn't present, and something like the following if it was found: {key: '3648', id: 'b'}.
"use strict";
function byId(id){return document.getElementById(id)}
function qs(sel,parent=document){return parent.querySelector(sel)}
function qsa(sel,parent=document){return parent.querySelectorAll(sel)}
window.addEventListener('load', onLoaded, false);
var rawData = {
"someID": "16385421",
"items": {
"9836": {
"id": "a"
},
"3648": {
"id": "b"
},
"7738": {
"id": "c"
}
}
};
function getIDs(data, searchItemId)
{
let keys = Object.keys(data.items);
let result = {};
keys.forEach( keyFunc );
return result;
function keyFunc(elem, index, collection)
{
if (data.items[elem].id == searchItemId)
{
result.key = elem;
result.id = searchItemId;
}
}
}
function onLoaded(evt)
{
console.log( getIDs(rawData, "b") );
}
You can do:
const obj = {
someID: '16385421',
items: {
9836: {
id: 'a',
},
3648: {
id: 'b',
},
7738: {
id: 'c',
},
},
}
const getParentObjectByValue = (obj, value) => {
const key = Object.keys(obj.items).find((k) => obj.items[k].id === value)
return key ? { [key]: obj.items[key].id } : undefined
}
console.log(getParentObjectByValue(obj, 'b'))
console.log(getParentObjectByValue(obj, 'zz'))

Loop through nested array to return values of object

I have a nested array and what I was trying to do was get all the values of the object embedded inside the array. I am currently getting each embedded object and calling Object.values to get the values but this method isn't efficient when the array size is big. Is there a way to loop through the array and return the values of each object? Any help is appreciated. Thanks in advance.
const data = [{"path":"uploads\\20211115000755-package.json"},{"path":"uploads\\20211115012255-index.html"},{"path":"uploads\\20211115014342-dataServerMid.js"},{"path":"uploads\\20211115031212-index.js"},{"path":"uploads\\20211115031218-uploadDataServer.js"},{"path":"uploads\\20211115031232-index.js"},{"path":"uploads\\20211115031244-dataServerMid.js"},{"path":"uploads\\20211115031250-uploadData.css"},{"path":"uploads\\20211115031303-20211115012255-index.html"},{"path":"uploads\\20211115031318-20211115031303-20211115012255-index.html"},{"path":"uploads\\20211115050204-exportsCapture.JPG"},{"path":"uploads\\20211115052347-[FREE] Stunna 4 Vegas x DaBaby x NLE Choppa Type Beat Call of Duty (320 kbps).mp3"},{"path":"uploads\\20211115200304-Readme.docx"},{"path":"uploads\\20211115202751-Visual Artist Series Fall 2019Corrected.docx"},{"path":"uploads\\20211115203354-ln command examples.docx"},{"path":"uploads\\20211115210027-Q2.docx"},{"path":"uploads\\20211116011817-Fall 2019 ABCD Plattsburgh Syllabi Course Description.docx"}]
//change this to loop and return all the values instead of having to call by index
const dataValues = [Object.values(data[0]).toString(), Object.values(data[1]).toString(), Object.values(data[2]).toString()]
console.log(dataValues)
UPDATE: I tried #yousaf's method. It worked for my 3 item array but not for this:
const data = [{
"path": "uploads\\20211115000755-package.json"
}, {
"path": "uploads\\20211115012255-index.html"
}, {
"path": "uploads\\20211115014342-dataServerMid.js"
}, {
"path": "uploads\\20211115031212-index.js"
}, {
"path": "uploads\\20211115031218-uploadDataServer.js"
}, {
"path": "uploads\\20211115031232-index.js"
}, {
"path": "uploads\\20211115031244-dataServerMid.js"
}, {
"path": "uploads\\20211115031250-uploadData.css"
}, {
"path": "uploads\\20211115031303-20211115012255-index.html"
}, {
"path": "uploads\\20211115031318-20211115031303-20211115012255-index.html"
}, {
"path": "uploads\\20211115050204-exportsCapture.JPG"
}, {
"path": "uploads\\20211115052347-[FREE] Stunna 4 Vegas x DaBaby x NLE Choppa Type Beat Call of Duty (320 kbps).mp3"
}, {
"path": "uploads\\20211115200304-Readme.docx"
}, {
"path": "uploads\\20211115202751-Visual Artist Series Fall 2019Corrected.docx"
}, {
"path": "uploads\\20211115203354-ln command examples.docx"
}, {
"path": "uploads\\20211115210027-Q2.docx"
}, {
"path": "uploads\\20211116011817-Fall 2019.docx"
}]
//change this to loop and return all the values instead of having to call by index
const dataValues = data.map((obj, idx) => obj["path" + (idx + 1)])
console.log(dataValues)
Use a for...of to iterate over the array, and then push the value to a new array.
const data=[{path1:"uploads\\20211115000755-package.json"},{path2:"uploads\\20211115012255-index.html"},{path3:"uploads\\20211115014342-dataServerMid.js"}];
const arr = [];
for (const obj of data) {
const [value] = Object.values(obj);
arr.push(value);
}
console.log(arr);
Or you can use map.
const data=[{path1:"uploads\\20211115000755-package.json"},{path2:"uploads\\20211115012255-index.html"},{path3:"uploads\\20211115014342-dataServerMid.js"}];
const arr = data.map(obj => {
const [value] = Object.values(obj);
return value;
});
console.log(arr);
Use for loop for iterate data
const data = [{
"path1": "uploads\\20211115000755-package.json"
}, {
"path2": "uploads\\20211115012255-index.html"
}, {
"path3": "uploads\\20211115014342-dataServerMid.js"
}]
const dataValues = [];
for(var i = 0; i < data.length; i++)
{
dataValues.push(Object.values(data[i]).toString())
}
console.log(dataValues)
This may help You. Try it out..
function nestedLoop(obj) {
const res = {};
function recurse(obj, current) {
for (const key in obj) {
let value = obj[key];
if(value != undefined) {
if (value && typeof value === 'object') {
recurse(value, key);
} else {
// Do your stuff here to var value
res[key] = value;
}
}
}
}
recurse(obj);
return res;
}

Search multiple elements by key inside multiple json structures

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

javascript how to compare only keys and not values of json

I have two nested JSON objects
//Json object1
{
"version": "1",
"user": {
"id": 123
}
}
//Json object2 =
{
"version": "1",
"user": {
"i": 123
}
}
1)It should only check for keys and not values during comparison.
So above should return false and below should return true
2) It should also follow the structure say user.id is not the same as just id.
//Json object1
{
"version": "1",
"user": {
"id": 123
}
}
//Json object2
{
"version": "1",
"user": {
"id": 12
}
}
I have tried the code below but to no avail
exports.compareObjects = async(model, response) => {
switch (Object.prototype.toString.call(model)) {
case '[object]':
var x;
var mKeys = Object.keys(model);
for (x in mKeys) {
return this.compareObjects(Object.keys(model)[x], Object.keys(response)[x]);
}
break;
case '[object Object]':
var x1;
var mKeys1 = Object.keys(model);
for (x1 in mKeys1) {
return this.compareObjects(Object.keys(model)[x1], Object.keys(response)[x1]);
}
break;
case '[object Array]':
return this.compareObjects(model[0], response[0]);
// case '[object String]':
// return model === response;
default:
return true;
}
};
This uses a recursive key search to build out an array of keys in each object you want to compare.
It tests fairly strict equality (no extra keys in either object)
let obj1 = JSON.parse(`{
"version": "1",
"user": {
"id": 123
}
}`);
let obj2 = JSON.parse(`{
"version": "1",
"user": {
"i": 123
}
}`);
let obj3 = JSON.parse(`{
"version": "1",
"user": {
"id": 123
}
}`);
let obj4 = JSON.parse(`{
"version": "1",
"user": {
"id": 12
}
}`);
let test1 = structureIsEqual(obj1, obj2);
let test2 = structureIsEqual(obj3, obj4);
console.log('Structure of first two match: ' + test1);
console.log('Structure of second two match: ' + test2);
function structureIsEqual(obj1, obj2) {
let tree1 = getKeys(obj1).sort();
let tree2 = getKeys(obj2).sort();
if(tree1.length !== tree2.length)
return false;
let mismatch = tree1.find((x, idx) => tree2[idx] !== x);
return !mismatch;
}
function getKeys(obj) {
return recursiveKeys(obj, [], []);
}
function recursiveKeys(obj, result, todo, root = '') {
Object.keys(obj).forEach(key => {
if(typeof obj[key] === 'object') {
result.push(root + key);
todo.push({ obj: obj[key], root: root + key + '.' });
} else {
result.push(root + key);
}
});
if(todo.length > 0) {
let todoItem = todo.pop();
return recursiveKeys(todoItem.obj, result, todo, todoItem.root);
}else {
return result;
}
}
Could be you could fix it by this line
return this.compareObjects(Object.keys(model)[x1], Object.keys(response)[x1]);
Instead do
return this.compareObjects(model[x1], response[x1]);
I would do it like this
1. you only need to compare objects (all other dont have keys)
2. recurse if value is also object
function compare(obj,model){
let keys=Object.keys(model)
let thisLevelOK=true
for (let key in keys.length){
if (obj[key]===undefined){
thisLevelOK=false
break
} else if (model[key].toString()=="[object Object]" && compare(obj[key],model[key])==false){
thisLevelOK=false
break
}
}
//in case obj has more keys then model
thisLevelOK=thisLevelOK && compare(model,obj)
return thisLevelOK
}
var compareObjects = (model, response) => {
switch (Object.prototype.toString.call(model)) {
case '[object]':
var x;
var mKeys = Object.keys(model);
for (x in mKeys) {
return this.compareObjects(Object.keys(model)[x], Object.keys(response)[x]);
}
break;
case '[object Object]':
var x1;
var mKeys1 = Object.keys(model);
for (x1 in mKeys1) {
let t = this.compareObjects(Object.keys(model)[x1], Object.keys(response)[x1]);
if(!t){
return false
}
if(typeof model[mKeys1[x1]] == "object"){
return this.compareObjects(model[mKeys1[x1]], response[mKeys1[x1]])
}
}
case '[object Array]':
return this.compareObjects(model[0], response[0]);
case '[object String]':
return model === response;
default:
return true;
}
};
let a = {
"version": "1",
"user": {
"id": 123,
"n":"d",
"j":{
"ns":"m"
}
}
}
let b = {
"version": "1",
"user": {
"id": 123,
"n":"d",
"j":{
"ns":"m"
}
}
}
var t = compareObjects(a,b)
console.log(t)

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