Check if array of objects contain certain key - javascript

I need to determine if a certain key exists in an array of objects.
Here is a sample array:
arrOfObj = [{
"mainKey1": {
"subKey1": {
"innerKey1": {
"innerMostKey1": {
"key1": "value"
}
}
}
}
}, {
"mainKey2": {
"key2": "value"
}
}, {
"mainKey3": {
"subKey3": {
"key3": "value"
}
}
}
]
I was trying to do this but I get the wrong output:
const objKeys = Object.keys(arrOfObj)
console.log('objKeys = ' + JSON.stringify(arrOfObj))
Output is the index numbers:
objKeys = ["0", "1", "2"]
I want to have a function that works like this:
var isKeyPresent = checkKeyPresenceInArray('mainKey3')
Please note though that I only need to check the topmost level in the objects - in above example, these are the main keys (mainKey1, etc) and that their content is dynamic (some others have deeply nested object inside and some not so.
Help!

You can try using array.some():
let checkKeyPresenceInArray = key => arrOfObj.some(obj => Object.keys(obj).includes(key));
let arrOfObj = [{
"mainKey1": {
"subKey1": {
"innerKey1": {
"innerMostKey1": {
"key1": "value"
}
}
}
}
}, {
"mainKey2": {
"key2": "value"
}
}, {
"mainKey3": {
"subKey3": {
"key3": "value"
}
}
}
]
let checkKeyPresenceInArray = key => arrOfObj.some(obj => Object.keys(obj).includes(key));
var isKeyPresent = checkKeyPresenceInArray('mainKey3')
console.log(isKeyPresent);

You can iterate through the array, check and see if any of the objects has the key that you are looking for, and return true if it does. If you don't find the key, then the for loop will complete and it will return false.
arrOfObj = [{
"mainKey1": {
"subKey1": {
"innerKey1": {
"innerMostKey1": {
"key1": "value"
}
}
}
}
}, {
"mainKey2": {
"key2": "value"
}
}, {
"mainKey3": {
"subKey3": {
"key3": "value"
}
}
}
]
function arrayHasKey(arr, key) {
for (const obj of arr) {
if (key in obj) { return true; }
}
return false;
}
console.log(arrayHasKey(arrOfObj, "mainKey2"))
console.log(arrayHasKey(arrOfObj, "mainKey10"))

this will work,it returns boolean value:
arrOfObj.hasOwnProperty('mainKey3');

You can use some with hasOwnProperty like this :
let checkKeyPresenceInArray = (key) => arrOfObj.some((o) => o.hasOwnProperty(key));

You have to use hasOwnProperty method to check if the key is available in the objects in that array -
var c = 0;
arrOfObj.forEach(e => {
if(e.hasOwnProperty("mainKey1")){
c++;
}
});
if(c > 0 && c == arrOfObj.length){
console.log("The key is found in all the objects in the array.");
}
else if(c == 0){
console.log("The key is not found in any objects in the array");
}
else{
console.log("The key is found in some objects in the array");
}

It is possibly to apply JSON.stringify() for that purpose:
let list = [{
"data1": {
"subKey1": {
"innerKey1": {
"innerMostKey1": {
"key1": "value"
}
}
}
}
}, {
"data2": {
"key2": "value"
}
}, {
"data3": {
"subKey3": {
"key3": "value"
}
}
}
]
let checkIfInArray = key => list.some(obj => JSON.stringify(obj).indexOf(key) > -1);
var result = checkIfInArray('key2')
alert(result);

Related

Get path to JSON object by key?

Given the following object:
const ourObject = {
"payload": {
"streams": [
{
"children": {
"2165d20a-6276-468f-a02f-1abd65cad618": {
"additionalInformation": {
"narrative": {
"apple": "A",
"banana": "B"
},
"myInventory": {
"fruits": [
{
"name": "apple"
},
{
"name": "banana"
}
]
}
}
}
}
}
]
}
};
We're trying to find the path of myInventory, the issue is that the children's uuid will be different each time. Any idea how we can get the path to myInventory by providing it as a key and get the json path to it?
If things are dynamic, a programmatic key search could help
const ourObject = {
"payload": {
"streams": [
{
"children": {
"2165d20a-6276-468f-a02f-1abd65cad618": {
"additionalInformation": {
"narrative": {
"apple": "A",
"banana": "B"
},
"myInventory": {
"fruits": [
{
"name": "apple"
},
{
"name": "banana"
}
]
}
}
}
}
}
]
}
};
const getPath = (key, o) => {
if (!o || typeof o !== "object") {
return "";
}
const keys = Object.keys(o);
for(let i = 0; i < keys.length; i++) {
if (keys[i] === key ) {
return key;
}
const path = getPath(key, o[keys[i]]);
if (path) {
return keys[i] + "." + path;
}
}
return "";
};
const getValueForKey = (key, o) => {
if (!o || typeof o !== "object") {
return undefined;
}
const keys = Object.keys(o);
for(let i = 0; i < keys.length; i++) {
if (keys[i] === key ) {
return o[key];
}
const value = getValueForKey(key, o[keys[i]]);
if (value) {
return value;
}
}
return undefined;
}
console.log(getPath("myInventory", ourObject))
console.log(getValueForKey("myInventory", ourObject))
Not sure if I understand the question right but
let uuid = '2165d20a-6276-468f-a02f-1abd65cad618';
ourObject.payload.streams[0].children[uuid].additionalInformation.myInventory
var changingKey = Object.keys(ourObject["payload"]["streams"][0]["children"])[0];
console.log(ourObject["payload"]["streams"][0]["children"][changingKey]["additionalInformation"]["myInventory"]);
Okay, you could create a helper function that gets the UUID. Since it's an object, the lookup is close to O(1) especially given the case that the children has only one key-value pair here.
function getUUIDFromPayload(payload) {
let obj = payload.streams[0].children
let uuid = Object.keys(obj)[0]
return uuid
}
Usage
const uuid = getUUIDFromPayload(payload)
ourObject.payload.streams[0].children[uuid].additionalInformation.myInventory

How to create object using pair values from another object in javascript

How to create object using pair values from another object in javascript
Input:
{
firstObject:{
{
"version":"1000",
"issue":"issue1"
},
{
"version":"1001",
"issue":"issue2"
},
{
"version":"1000",
"issue":"issue3"
}
}
}
Above is my input and I want output as following:
{
newObject:{
"1000":["issue1", "issue3"],
"1001":["issue2"]
}
}
Your Input is not a valid JSON. firstObject should be an array instead of object.
Demo
var obj = {
"firstObject": [{
"version": "1000",
"issue": "issue1"
},
{
"version": "1001",
"issue": "issue2"
},
{
"version": "1000",
"issue": "issue3"
}
]
};
var newObject = {};
obj.firstObject.map((item) => {
if( !newObject[ item.version ]){
newObject[item.version] = [];
}
newObject[item.version].push(item.issue);
});
console.log({ newObject });
You can try this
let input = {
firstObject:[
{
"version":"1000",
"issue":"issue1"
},
{
"version":"1001",
"issue":"issue2"
},
{
"version":"1000",
"issue":"issue3"
}
]
}
function createNewObject( input ){
let output= {};
input.firstObject.map(( item ) => {
if( !output[ item.version ]){
output[ item.version ] =[]
}
output[ item.version ].push( item.issue )
})
return({
newObject: output
})
}
console.log( createNewObject( input ))

javascript: Sourcing defaults for one json object from another - handling arrays in different sort order

I am receiving a json as parameter and I also have a template base json. I need to check that all objects of the template json should are present in the tgt json and if not, need to initialize those variables with template json.
Following is my implementation.
var jsonBase = {
"Et":"Val_Retain",
"A1": {
"A12": {
"A12Array": [
{
"key1": "val1"
},
{
"key2": "val2"
}
]
}
}
}
var jsonTgt = {
"Et":"OldVal",
"A1": {
"A12": {
"A12Array": [
{
"key1": "val1Old_Retain"
}
]
}
}
}
initKeys(jsonBase,jsonTgt)
function initKeys(obj,tgt) {
Object.keys(obj).forEach(function(element, key, _array) {
var cur;
if (typeof(tgt[element])=="undefined") {
tgt[element]=obj[element]
}
if (typeof(obj[element])=="object") {
initKeys(obj[element],tgt[element])
}
})
}
console.log(JSON.stringify(jsonTgt))
The output is:
{
"Et": "OldVal",
"A1": {
"A12": {
"A12Array": [{
"key1": "val1Old_Retain"
}, {
"key2": "val2"
}
]
}
}
}
There are two questions:
Is this correct approach or there could be a more efficient or a
simpler one with available js/nodejs libs?
More Importantly - What do I do in case if the array sort order doesn't match with template as below.
Changed sort order
var json2 = {
"Et":"OldVal",
"A1": {
"A12": {
"A12Array": [
{
"key2": "val1Old_Retain"
}
]
}
}
}
The above produces the following output:
{
"Et": "OldVal",
"A1": {
"A12": {
"A12Array": [{
"key2": "val1Old_Retain",
"key1": "val1"
}, {
"key2": "val2"
}
]
}
}
}
as against the desired:
{
"Et": "OldVal",
"A1": {
"A12": {
"A12Array": [{
"key1": "val1"
}, {
"key2": "val1Old_Retain"
}
]
}
}
}
Here is the first sample code I have been able to make and it works, however, I think that the way you implemented your code is wrong since I am pretty sure you could have done something much simpler if you had in mind functional programming methods i.e. those native methods from mdn, and those ones from lodash library don't forget to mark as answered if I did, otherwise please comment so I get more information about your exact situation
var _ = require('lodash')
let jsonInput = {
"Et": "Val_Retain",
"A1": {
"A12": {
"A12Array": [{
"key1": "val1"
}, {
"key2": "val2"
}]
}
}
}
let jsonInput2 = {
"Et": "OldVal",
"A1": {
"A12": {
"A12Array": [{
"key1": "val1Old_Retain"
}]
}
}
}
for (let key1 in jsonInput) {
if (key1 === 'Et') {
jsonInput[key1] = "OldVal"
} else {
for (let key2 in jsonInput[key1]) {
for (let key3 in jsonInput[key1][key2]) {
console.log(jsonInput[key1][key2][key3])
let listOfKeys = getKeys(jsonInput[key1][key2][key3])
console.log(listOfKeys)
console.log(jsonInput2[key1][key2])
console.log(key3)
let listOfKeys2 = getKeys(jsonInput2[key1][key2][key3])
console.log(listOfKeys2)
let uniqkeys = _.uniq(listOfKeys.concat(listOfKeys2))
let sortedUniqkeys = _.sortBy(uniqkeys)
let result = []
console.log('sortedUniqkeys', sortedUniqkeys)
sortedUniqkeys.forEach((key4, i) => {
let doc = {}
if (listOfKeys2.indexOf(key4) != -1) {
jsonInput2[key1][key2][key3].forEach((e, i) => {
if (e[key4]) {
doc[key4] = e[key4]
}
})
} else {
jsonInput[key1][key2][key3].forEach((e, i) => {
if (e[key4]) {
doc[key4] = e[key4]
}
})
}
result.push(doc)
console.log(key4, jsonInput[key1][key2][key3][key4])
console.log(result)
})
jsonInput[key1][key2][key3] = result
}
}
}
}
function getKeys(arr) {
console.log(arr)
return arr.reduce(function(accumulator, value, index, array) {
for (let key3 in value) {
accumulator.push(key3)
}
return accumulator
}, []);
}
console.log(JSON.stringify(jsonInput))

Cleaning up a JSON object that is full of objects with 1 attribute

I have a JSON object that's formatted like the following:
{
"ATTR1": {
"0":"Value1"
},
"ATTR2": {
"0":"Value2"
} //and so on
}
and this format holds for dozens of attributes. I'm looking for a way to have the JSON be more like:
{
"ATTR1": "Value1",
"ATTR2": "Value2" //and so on
}
Is there an easy way to do this in Javascript? I've tried something like:
for(var attr in obj) {
if(obj.hasOwnProperty(attr)) {
attr = attr[0];
}
}
But this hasn't been working. Any ideas?
Use reduce on the object's keys for that:
let foo = {
"ATTR1": {
"0":"Value1"
},
"ATTR2": {
"0":"Value2"
} //and so on
};
let res = Object.keys(foo).reduce((a,b) => {
a[b] = foo[b]['0'];
return a;
}, {});
console.log(res)
If you want to mutate the original obj, you can do this:
for(var attr in obj) {
if(obj.hasOwnProperty(attr)) {
obj[attr] = obj[attr][0];
}
}
you are close!
Try something like this:
var obj = {
"ATTR1": {
"0":"Value1"
},
"ATTR2": {
"0":"Value2"
} //and so on
};
var obj2 = {};
for(var attr in obj) {
if(obj.hasOwnProperty(attr)) {
obj2[attr] = obj[attr][0];
}
}
alert(JSON.stringify(obj2));
Fiddle: https://jsfiddle.net/coLxfeum/
Iterating over javascript objects is easier using Object.keys(), IMO. It's supported in the major browsers... Anyway, you want to iterate over the top level object, grabbing all of it's "smallObject" values and flatten them. You can make the checks as strict as you like (insisting on "0" keys etc), but fundamentally, it seems important that the values you are collapsing are single-value objects containing string values? Anyway - here's how you could do that:
var v1 = {
"ATTR1": {
"0": "Value1"
},
"ATTR2": {
"0": "Value2"
}
}
function flatten(obj) {
Object.keys(obj).forEach( function(attr) {
var smallObj = obj[attr];
var keys = Object.keys(smallObj);
if( keys.length === 1 && typeof smallObj[keys[0]] === 'string' ) { // && keys[0] === "0" ?
obj[attr] = smallObj[keys[0]];
} // else throw Error(...) ?
})
return obj;
}
console.log(flatten(v1));
> { ATTR1: 'Value1', ATTR2: 'Value2' }
Try this :
var jsonObj = {
"ATTR1": {
"0":"Value1"
},
"ATTR2": {
"0":"Value2"
}
};
var newJson = {};
for(var i = 0;i<Object.keys(jsonObj).length;i++) {
newJson[Object.keys(jsonObj)[i]] = jsonObj[Object.keys(jsonObj)[i]]["0"];
}
console.log(newJson);

Typescript: Is there a way to get all the keys in a Javascript object with nested properties?

For example, if i have
{
"key1":{
"key2":[
{
"key3":[
{
"key4":{
"key5":0
}
},
{
"key6":{
"key7":""
}
}
]
},
{
"key8":{
"key9":true
}
}
]
}
}
is there a way to get all the keys like this?
["key1", "key2", "key3", "key4", "key5", "key6", "key7", "key8", "key9"]
edit: i tried the suggestion here, but it didn't work out Typescript: what could be causing this error? "Element implicitly has an 'any' type because type 'Object' has no index signature"
You need a recursive function in order to iterate.
Try like this
var obj = {
"key1": {
"key2": [{
"key3": [{
"key4": {
"key5": 0
}
}, {
"key6": {
"key7": ""
}
}]
}, {
"key8": {
"key9": true
}
}]
}
};
var keys = [];
function collectKey(obj) {
if (obj instanceof Array) {
//console.log("array");
for (var i = 0; i < obj.length; i++) {
collectObj(obj[i]);
}
} else if (typeof obj == "object") {
//console.log("object");
collectObj(obj)
} else {
return;
}
}
function collectObj(obj) {
for (var i = 0; i < Object.keys(obj).length; i++) {
keys.push(Object.keys(obj)[i]);
collectKey(obj[Object.keys(obj)[i]]);
}
}
collectKey(obj);
console.log(keys);

Categories