Trying to get the object key of a nested JSON object - javascript

I need to get a list of all the key names in the following JSON object:
var myJSON = [
{
"Employees_Name": "Bill Sanders",
"Work_plan_during_my_absence": "Work from home",
"Assigned To-Manager Approval": [
"mymanager#gmail.com"
],
"AbsenceVacation_Summary": [
{
"Computed_Leave_Days": 2,
"From_Date": "2018-08-20",
"To_Date": "2018-08-21",
"Id": "Shccbcc230_a30f_11e8_9afa_25436d674c51"
}
],
"Leave_Type": "Work from Home",
"Reporting_Manager": "My Manager",
"Total_Days": 2,
}
]
When I use the Object.keys method, it retrieves only the top level key names:
var keys_arr = Object.keys(myJSON[0]);
console.log(keys_arr);
The result is an array:
"[ 'Employees_Name', 'Work_plan_during_my_absence', 'Assigned To-Manager
Approval', 'AbsenceVacation_Summary', 'Leave_Type', 'Reporting_Manager',
'Total_Days']"
The key names that are missing are the ones inside of 'AbsenceVacation_Summary'.
I think what I need to do is loop through the array of names returned and see if the value is an object or an array...but I don't know how to do this. Please advise.

You're right you need to walk your object structure recursively to discover nested objects and collects their keys:
function collectKeys(inputObject, outputKeys) {
if (Array.isArray(inputObject)) {
for(let i = 0; i < inputObject.length; i++) {
collectKeys(inputObject[i], outputKeys);
}
} else if (typeof inputObject === 'object') {
Object.keys(inputObject).forEach(function(key) {
outputKeys.push(key);
collectKeys(outputKeys[key], outputKeys);
});
}
}
var collectedKeys = [];
collectKeys(myJSON, collectedKeys);
Working fiddle here
Result will show in console
References
javascript typeof
javascript Array.isArray
javascript Array.forEach

Related

Finding nested object data using basic JavaScript

I want to loop through 600+ array items in an object and find one particular item based on certain criteria. The array in the object is called "operations" and its items are arrays themselves.
My goal is to get the index of operation's array item which has the deeply nested string "Go".
In the sample below this would be the first element. My problem is that I can check if an array element contains "call" and "draw" but I don't know how to test for the nested dictionary "foobar". I only have basic JavaScript available, no special libraries.
let json = {
"head": {},
"operations": [
[
"call",
"w40",
"draw",
{
"parent": "w39",
"style": [
"PUSH"
],
"index": 0,
"text": "Modify"
}
],
[
"call",
"w83.gc",
"draw",
{
"foobar": [
["beginPath"],
[
"rect",
0,
0,
245,
80
],
["fill"],
[
"fillText",
"Go",
123,
24
],
[
"drawImage",
"rwt-resources/c8af.png",
]
]
}
],
[
"create",
"w39",
"rwt.widgets.Menu",
{
"parent": "w35",
"style": [
"POP_UP"
]
}
],
[
"call",
"w39",
"draw",
{
"parent": "w35",
"style": [
"POP_UP"
]
}
]
]
};
let index = "";
let operationList = json.operations;
for (i = 0; i < operationList.length; i++) {
if (operationList[i].includes('call') && operationList[i].includes('draw')) //missing another check if the dictionary "foobar" exists in this element )
{
index = i;
}
}
document.write(index)
I'll preface by saying that this data structure is going to be tough to manage in general. I would suggest a scheme for where an operation is an object with well defined properties, rather than just an "array of stuff".
That said, you can use recursion to search the array.
If any value in the array is another array, continue with the next level of recursion
If any value is an object, search its values
const isPlainObject = require('is-plain-object');
const containsTerm = (value, term) => {
// if value is an object, search its values
if (isPlainObject(value)) {
value = Object.values(value);
}
// if value is an array, search within it
if (Array.isArray(value)) {
return value.find((element) => {
return containsTerm(element, term);
});
}
// otherwise, value is a primitive, so check if it matches
return value === term;
};
const index = object.operations.findIndex((operation) => {
return containsTerm(operation, 'Go');
});

converting array to object while considering keys of the same value

I am trying to figure out an easy way to convert an array of objects to an object
I have an array of objects that looks like this:
[
{
"id": "-LP9_kAbqnsQwXq0oGDT",
"value": Object {
"date": 1541482236000,
"title": "First",
},
},
.... more objects here
]
And id like to convert it to an object with the timestamps as the keys, and arrays of objects corresponding to that date. If that key already exists, then add the object to the corresponding array associated with that key
{
1541482236000:
[{
"id": "-LP9_kAbqnsQwXq0oGDT",
"value": Object {
"date": 1541482236000,
"title": "First",
},
},
{
"id": "-LP9_kAbqnsQwXqZZZZ",
"value": Object {
"date": 1541482236000,
"title": "Some other title",
},
},
.... more objects here
],
1541482236001:
[{
"id": "-LP9_kAbqnsQ1234",
"value": Object {
"date": 1541482236001,
"title": "Another title",
},
},
.... more objects here
]
}
I was able to achieve something similar using reduce. However it does not handle adding objects to the array when their key already exists.
calendarReminders = action.value.reduce((obj, reminder) => {
dateKey = moment(reminder.value.date).format('YYYY-MM-DD')
obj[dateKey] = [reminder]
return obj;
}, {});
How can I do this?
You just need to check whether the object is already a key and if not add it with the value of an array. Then you can just push() into it:
let arr = [{"id": "-LP9_kAbqnsQwXq0oGDT","value": {"date": 1541482236000,"title": "First",},},{"id": "SomID","value": {"date": 1541482236000,"title": "Some other title",},},{"id": "A different ID","value": {"date": 1541482236001,"title": "A third title",},}]
let calendarReminders = arr.reduce((obj, reminder) => {
(obj[reminder.value.date] || (obj[reminder.value.date] = [])).push(reminder)
return obj;
}, {});
console.log(calendarReminders)
If you want to set the keys to a different format with moment, you should be able to do that without changing the basic idea.
Please test the below code!
First you iterate through your array of data,
if your result object/dictionary already has the key then you just add the current item
otherwise you make the key and set the value
const data = [];
let result = {};
for (const item of data) {
const key = item.value.date;
if (result.hasOwnProperty(key)) {
const prevData = result[key];
result[key] = [...prevData, item];
} else {
result[key] = [item];
}
}

Retrieve Object from complex Array

I have this array :
var hemicycle = {
Group1 : [{
GroupName : "Les bests",
Member1 : [{
Name : "Loris Plasson",
Seat : 4,
Vignette : "PhotoURL"
}],
Member2 : [{
Name : "Anne-Sophie",
Seat : 3,
Vignette : "PhotoURL"
}]
}]
I want to push the object Member1 or Member2 on another object depending of the Seat value.
To do that I think I need to "search" for the Seat value with a for loop and retrieve the object, but all the examples I found on StackOverflow were with simple arrays like this :
var array = [
{ name:"string 1", value:"this", other: "that" },
{ name:"string 2", value:"this", other: "that" }
];
With those simple arrays they are able to use something like a for loop with array[i].
But in my case I really don't know what to do...
UPDATE : What I want : The Member object which include the corresponding Seat value searched. Then I push the Member object to another object.
Thanks for any help.
The data structure that you use doesn't reflect what you are trying to convey, and in addition is very heard to traverse.
I suggest creating an array of groups. Each group is an object, that has the members property, which is an array of member objects:
[{
"GroupName": "Les bests",
"members": [{
"Name": "Loris Plasson",
"Seat": 4,
"Vignette": "PhotoURL"
},
{
"Name": "Anne-Sophie",
"Seat": 3,
"Vignette": "PhotoURL"
}
]
}]
Using this structure, you find a member using 2 for loops - one to iterate the groups, and the other to iterate the members of each group. Once a member is found, the function returns the member's object immediately. If not undefined is returned:
var groups = [{"GroupName":"Les bests","members":[{"Name":"Loris Plasson","Seat":4,"Vignette":"PhotoURL"},{"Name":"Anne-Sophie","Seat":3,"Vignette":"PhotoURL"}]}];
var seatNum = 4;
function findMember(seatNum) {
var members;
for(var i = 0; i < groups.length; i++) {
members = groups[i].members;
for(var j = 0; j < members.length; j++) {
if(members[j].Seat = seatNum) {
return members[j];
}
}
}
}
var member = findMember(seatNum);
console.log(member);

Creating custom JSON object

I am having the below JSON object.
"Department": [
{
"depType": "Testing",
"name": "xyz",
"address":""
},
{
"deptype": "Developer",
"name": "abc"
}
]
I want to create another object based on the type of deptartment (depType). Something like this
"Testing":{
"name": "xyz",
"address":""
},
"Developer":{
"name": "abc"
}
With the help of Object.keys, I was able to get the keys
You had some Property-naming issues with camelCased "depType". Fix that.
Create a new copy of the desired object to manipulate using JSON.parse(JSON.stringify(orgObj))
Loop that object to find the desired Property "Department"
Since Department is an Array of Objects you need to loop that Array for(var i=0; i<dep.length; i++).
Than you'll need to match if that Array contains arrObj.hasOwnProperty( "depType" )
if successful you can than fill your new object with all the info newObj[arrObj.depType] = arrObj;
Since now, inside your new object there's also the good old "depType" property you can get rid of it using delete.
jsBin demo
var myjson = {
"Department": [
{
"depType": "Testing", // NOTE: "camelCase"
"name": "xyz",
"address":""
},
{
"depType": "Developer", // FIX: "camelCase" !!
"name": "abc"
}
]
};
function depTypify( orgObj ) {
var objCopy = JSON.parse(JSON.stringify(orgObj)); // Fresh copy
var newObj = {};
for(var prop in objCopy){
if(prop === "Department") {
var dep = objCopy[prop]; // get Department Array
for(var i=0; i<dep.length; i++) { // Loop array
var arrObj = dep[i]; // Explore Each Array Object
if(arrObj.hasOwnProperty( "depType" )) {
newObj[arrObj.depType] = arrObj;
delete arrObj.depType; // We don't need it any more
}
}
}
}
return newObj;
}
var myNewJson = depTypify( myjson );
if you do than console.log( myNewJson ) this is what you'll get:
[object Object] {
Developer: [object Object] {
name: "abc"
},
Testing: [object Object] {
address: "",
name: "xyz"
}
}
The nice thing is that your old json is still intact.

Search through multidimensional array JavaScript

I got stuck trying to retrive array items. So here is the deal. I have a two dimentional array which has value and key so example of my data is:
[
Object { css="SS", title="Apple"},
Object { css="SS", title="Orange"},
Object { css="SS", title="Banana"}
]
I want to see if an object exists in the array above. And I have no idea why its not working, here is my code to find the object:
jQuery.inArray("Apple", fruits["title"]); //this returns -1 why?
Any ideas how to search two dimensional array?
This is not a 2D array, this is an array of objects, so this should work:
for (var i = 0; i < array.length; i++) {
console.log(array[i].title); //Log the title of each object.
if (array[i].title == "Apple") {
console.log("Found apple!");
}
}
Also, objects are key/val pairs, denoted by key : val, not key = val. Your array has syntax errors and shouldn't run.
To be pedantic, you have an array of objects, not a 2d array. Also your syntax for the object parameters is incorrect.
You can use filter() on the array to find the values:
var array = [
{ css: "SS", title: "Apple"},
{ css: "SS", title: "Orange"},
{ css: "SS", title: "Banana"}
];
var matches = array.filter(function (obj) { return obj.title == "Apple" });
if (matches.length) {
// Apple was in the array...
}
If you have an object like this
var peoples = [
{ "name": "bob", "dinner": "pizza" },
{ "name": "john", "dinner": "sushi" },
{ "name": "larry", "dinner": "hummus" }
];
Ignore what's below. Use the filter method!
peoples.filter(function (person) { return person.dinner == "sushi" });
// => [{ "name": "john", "dinner": "sushi" }]
You can search for people who have "dinner": "sushi" using a map
peoples.map(function (person) {
if (person.dinner == "sushi") {
return person
} else {
return null
}
}); // => [null, { "name": "john", "dinner": "sushi" }, null]
or a reduce
peoples.reduce(function (sushiPeople, person) {
if (person.dinner == "sushi") {
return sushiPeople.concat(person);
} else {
return sushiPeople
}
}, []); // => [{ "name": "john", "dinner": "sushi" }]
I'm sure you are able to generalize this to arbitrary keys and values!
fruits probably is a array, fruits["title"] therefor doesn't exist.
You might want to transform your data:
var fruitTitles = fruits.map(function(f) { return f.title; });
jQuery.inArray("Apple", fruitTitles);
From the jQuery docs:
jQuery.inArray( value, array [, fromIndex ] )
I've never used this method, but a quick guess:
var hasIt = jQuery.inArray({css:"SS",title:"Apple"}, myArray);
As the $.inArray() documentation explains, the first argument to the function is the value to search for. Your array does not have any elements that are equal to the string "Apple" that you have supplied in the first argument because none of your array elements are strings (they're all objects).
The second argument to $.inArray() is supposed to be the array itself, but (assuming fruits is the array you show) fruits["title"] is undefined because your array has no property called "title", only the objects in the array have that property.
Try this instead:
var index = $.inArray("Apple", $.map(fruits, function(el) { return el.title; }));
try this code
var fruits = [
{ css:"SS", title:"Apple"},
{ css:"SS", title:"Orange"},
{ css:"SS", title:"Banana"}
];
jQuery.grep(fruits,function(fruit){return fruit.title == 'Apple'});

Categories