remove keys with empty values from json using JS - javascript

{
"top": [{
"language": "English",
"value": ""
}, {
"language": "German",
"value": "hASTA"
}],
"bottom": [{
"language": "English",
"value": "jfgfjg"
}, {
"language": "German",
"value": "fkjhf"
}],
"In": "12 am",
"Out": "3 am",
"Type": ""
}
Hi guys, I want to remove the keys that have empty values, I tried using filter but that showed me error in google sheets.
I want to send only the data to API that has values.
In this case, for
language:german, the value is empty so i Would skip sending top. to the API.
the json to be sent:
{
"bottom": [{
"language": "English",
"value": "jfgfjg"
}, {
"language": "German",
"value": "fkjhf"
}],
"In": "12 am",
"Out": "3 am"
}
code used:
apidata = userdata.filter(function(x) { return x !== "" });
Can you please guide me on how to do this?

userdata.filter won't filter the keys of the object.
You can use Array.reduce to create your new object
const json = {
"top": [{
"language": "English",
"value": ""
}, {
"language": "German",
"value": "hASTA"
}],
"bottom": [{
"language": "English",
"value": "jfgfjg"
}, {
"language": "German",
"value": "fkjhf"
}],
"In": "12 am",
"Out": "3 am",
"Type": ""
};
// returns true if it contains a falsy value
// this function is recursive
function checkFalsy(ptr) {
// If we are dealing with an array
if (ptr instanceof Array) {
return ptr.some(x => checkFalsy(x));
}
// If we have a string
if (typeof ptr === 'string') {
return ptr.length === 0;
}
// If we have an object
if (Object.keys(ptr).length) {
return Object.keys(ptr).some(y => checkFalsy(ptr[y]));
}
// anything else
return !!ptr;
}
const filteredJson = Object.keys(json).reduce((tmp, x) => {
// If we are dealing with an array
if (checkFalsy(json[x]) === false) {
tmp[x] = json[x];
}
return tmp;
}, {});
console.log(filteredJson);

Related

How to change key name of an object by comparing another object?

I have an array of object and another object containing labels, how to write a simple function to compare both array and replace the key name.
input = [
{
"id": "AAP",
"prd": "PL",
"trcode": "NORTH",
"accountNo": "12345",
"prBranch": null,
"prDealer": "Dealer 1",
"prUser": "CFG",
"staticBranch": "YES",
"staticCustomer": "NO",
"reason": "Invalid request"
},
{
"id": "AAC",
"prd": "PL",
"trcode": "WEST",
"accountNo": "67890",
"prBranch": null,
"prDealer": "Dealer 2",
"prUser": "DFG",
"staticBranch": "YES",
"staticCustomer": "NO",
"reason": "Invalid request"
}
],
labels = [
{
"key": "id",
"value": "USER"
},
{
"key": "prd",
"value": "PRODUCT"
},
{
"key": "trcode",
"value": "TRANSFER_CODE"
},
{
"key": "accountNo",
"value": "ACCOUNT_NUMBER"
},
{
"key": "prBranch",
"value": "PROCESSING_BRANCH"
},
{
"key": "prDealer",
"value": "PROCESSING_DEALER"
},
{
"key": "prUser",
"value": "PROCESSING_USER"
},
{
"key": "staticBranch",
"value": "STATIC_BRANCH"
},
{
"key": "staticAgent",
"value": "STATIC_AGENT"
},
{
"key": "reason",
"value": "Reason"
}
]
Expected output =
[
{
"USER": "AAP",
"PRODUCT": "PL",
"TRANSFER_CODE": "NORTH",
"ACCOUNT_NUMBER": "12345",
"PROCESSING_BRANCH": null,
"PROCESSING_DEALER": "Dealer 1",
"PROCESSING_USER": "CFG",
"STATIC_BRANCH": "YES",
"STATIC_CUSTOMER": "NO",
"Reason": "Invalid request"
},
{
"USER": "AAC",
"PRODUCT": "PL",
"TRANSFER_CODE": "WEST",
"ACCOUNT_NUMBER": "67890",
"PROCESSING_BRANCH": null,
"PROCESSING_DEALER": "Dealer 2",
"PROCESSING_USER": "DFG",
"STATIC_BRANCH": "YES",
"STATIC_CUSTOMER": "NO",
"Reason": "Invalid request"
}
],
You can use Array#map to convert each object in the array. For each object, we can map over the entries of the object and use Array#find to look for the replacement key if it exists. Finally, Object.fromEntries converts the array of key-value pairs back to an object.
let input=[{id:"AAP",prd:"PL",trcode:"NORTH",accountNo:"12345",prBranch:null,prDealer:"Dealer 1",prUser:"CFG",staticBranch:"YES",staticCustomer:"NO",reason:"Invalid request"},{id:"AAC",prd:"PL",trcode:"WEST",accountNo:"67890",prBranch:null,prDealer:"Dealer 2",prUser:"DFG",staticBranch:"YES",staticCustomer:"NO",reason:"Invalid request"}],labels=[{key:"id",value:"USER"},{key:"prd",value:"PRODUCT"},{key:"trcode",value:"TRANSFER_CODE"},{key:"accountNo",value:"ACCOUNT_NUMBER"},{key:"prBranch",value:"PROCESSING_BRANCH"},{key:"prDealer",value:"PROCESSING_DEALER"},{key:"prUser",value:"PROCESSING_USER"},{key:"staticBranch",value:"STATIC_BRANCH"},{key:"staticAgent",value:"STATIC_AGENT"},{key:"reason",value:"Reason"}];
const res = input.map(o =>
Object.fromEntries(Object.entries(o)
.map(([k,v])=>[labels.find(({key})=>key===k)?.value ?? k, v])));
console.log(res)
.as-console-wrapper{max-height:100%!important;top:0}
Loop through input and inside the loop use a for...in loop to loop through each property.
Inside the loop, loop through labels and get the corresponding value to that property, set the value of the property to the new property and delete the previous property.
input.forEach(e => {
for (const l in e) {
var a;
labels.forEach(e => {
e.key == l && (a = e.value)
}), e[a] = e[l], delete e[l]
}
});
Demo:
input=[{id:"AAP",prd:"PL",trcode:"NORTH",accountNo:"12345",prBranch:null,prDealer:"Dealer 1",prUser:"CFG",staticBranch:"YES",staticCustomer:"NO",reason:"Invalid request"},{id:"AAC",prd:"PL",trcode:"WEST",accountNo:"67890",prBranch:null,prDealer:"Dealer 2",prUser:"DFG",staticBranch:"YES",staticCustomer:"NO",reason:"Invalid request"}];var labels=[{key:"id",value:"USER"},{key:"prd",value:"PRODUCT"},{key:"trcode",value:"TRANSFER_CODE"},{key:"accountNo",value:"ACCOUNT_NUMBER"},{key:"prBranch",value:"PROCESSING_BRANCH"},{key:"prDealer",value:"PROCESSING_DEALER"},{key:"prUser",value:"PROCESSING_USER"},{key:"staticBranch",value:"STATIC_BRANCH"},{key:"staticAgent",value:"STATIC_AGENT"},{key:"reason",value:"Reason"}];
input.forEach(e=>{for(const l in e){var a;labels.forEach(e=>{e.key==l&&(a=e.value)}),e[a]=e[l],delete e[l]}});
console.log(input);
One of the first thing I would to is to use an object instead of an array for your key association:
labels = {
"id": "USER",
"prd": "PRODUCT",
"trcode": "TRANSFER_CODE",
"accountNo": "ACCOUNT_NUMBER",
"prBranch": "PROCESSING_BRANCH",
"prDealer": "PROCESSING_DEALER",
"prUser": "PROCESSING_USER",
"staticBranch": "STATIC_BRANCH",
"staticAgent": "STATIC_AGENT",
"reason": "Reason"
}
Now if you want to map them to your new object you can do
function renameKeys(src) {
let entries = Object.entries(src)
let renamedEntries = entries.map(([key, value]) => [
labels[key] || key,
/* I added a fallback to the original key
if it's not found to avoid undefined keys */
value,
])
return Object.fromEntries(renamedEntries)
}
// and use it like so
console.log(input.map(renameKeys))
You can just iterate them and assign the values as below
for (var object of input) {
for (var mapping of labels) {
if (object[mapping.key] !== undefined) {
object[mapping.value] = object[mapping.key];
delete object[mapping.key];
}
}
}
console.log(input);
The way I'd do it would be:
const input = [{
"id": "AAP",
"prd": "PL",
"trcode": "NORTH",
"accountNo": "12345",
"prBranch": null,
"prDealer": "Dealer 1",
"prUser": "CFG",
"staticBranch": "YES",
"staticCustomer": "NO",
"reason": "Invalid request"
},
{
"id": "AAC",
"prd": "PL",
"trcode": "WEST",
"accountNo": "67890",
"prBranch": null,
"prDealer": "Dealer 2",
"prUser": "DFG",
"staticBranch": "YES",
"staticCustomer": "NO",
"reason": "Invalid request"
}
];
const labels = [{
"key": "id",
"value": "USER"
},
{
"key": "prd",
"value": "PRODUCT"
},
{
"key": "trcode",
"value": "TRANSFER_CODE"
},
{
"key": "accountNo",
"value": "ACCOUNT_NUMBER"
},
{
"key": "prBranch",
"value": "PROCESSING_BRANCH"
},
{
"key": "prDealer",
"value": "PROCESSING_DEALER"
},
{
"key": "prUser",
"value": "PROCESSING_USER"
},
{
"key": "staticBranch",
"value": "STATIC_BRANCH"
},
{
"key": "staticAgent",
"value": "STATIC_AGENT"
},
{
"key": "reason",
"value": "Reason"
}
]
// 1. create an object mapping the old labels to the new ones
const betterLabels = labels.reduce((outObj, item) => {
outObj[item.key] = item.value;
return outObj;
}, {});
// 2. use `Array.prototype.map` to traverse the input array
// and `Array.prototype.reduce` with the label mapping object
// to generate the output array
const output = input.map(item => {
return Object.entries(item).reduce((newItem, [key, value]) => {
betterLabels[key]
? newItem[betterLabels[key]] = value
: newItem[key] = value
return newItem
}, {});
});
//test
console.log(output);

Look up values in an array using looping forEach Google Apps Script Javascript

I have an object that looks like the following {key: id numbers}
var obj = {
"c4ecb": {id: [3]},
"a4269": {id: [34,36]},
"d76fa": {id: [54,55,60,61]},
"58cb5": {id: [67]}
}
How do I loop each above id in the following array, and return the label?
var response =
{
"success": true,
"data": [
{
"key": "c4ecb",
"name": "fruits",
"options": [
{
"label": "strawberry",
"id": 3
},
{
"label": "apple",
"id": 4
},
{
"label": "pineapple",
"id": 5
},
{
"label": "Other",
"id": 31
}
],
}
]
},
{
"success": true,
"data": [
{
"key": "a4269",
"name": "vegetables",
"options": [
{
"label": "lettuce",
"id": 34
},
{
"label": "cucumber",
"id": 35
},
{
"label": "radish",
"id": 36
}
],
}
]
},
{
"success": true,
"data": [
{
"key": "d76fa",
"name": "pasta",
"options": [
{
"label": "spaghetti",
"id": 54
},
{
"label": "rigatoni",
"id": 55
},
{
"label": "linguine",
"id": 56
},
{
"label": "lasagna",
"id": 60
},
{
"label": "fettuccine",
"id": 61
}
],
}
]
}
Finally, what I want to do is look up the key and return a string of id values.
For example, input c4ecb and output strawberry. Input a4269 and output lettuce, radish. Input d76fa and output "spaghetti, rigatoni, lasagna, fettuccine"
I think to join the multiple labels output into one string I could use something like
array.data.vegetables.map(vegetables => vegetables.value).join(', ')].toString();
So in the end I want to have something like
var fruits = [some code that outputs "strawberry"];
var vegetables = [some code that outputs "lettuce, radish"];
var pasta = [some code that outputs "spaghetti, rigatoni, lasagna, fettuccine"];
What I've tried so far:
The following loop will return the id only if there is one id to be called for: e.g. only in case one where {id: 3} but returns null in cases like {id: 34,36} (because it's looking for '34,36' in id, which doesn't exist - I need to look for each one individually.
response.data.forEach(({key, options}) => {
if (obj[key]) {
options.forEach(({id, label}) => {
if (id == obj[key].id) obj[key].label = label;
});
}
});
console.log(obj)
Filter the response object to focus on the category that matches the id.
Map over the options array and select the items which appear in obj[id].
Finally convert the filtered results to a string.
See filteredLabelsAsString() function below for implementation.
var obj = {
"c4ecb": {"id": [3]},
"a4269": {"id": [34,36]},
"d76fa": {"id": [54,55,60,61]},
"58cb5": {"id": [67]}
}
var response =
[{
"success": true,
"data": [
{
"key": "c4ecb",
"name": "fruits",
"options": [
{
"label": "strawberry",
"id": 3
},
{
"label": "apple",
"id": 4
},
{
"label": "pineapple",
"id": 5
},
{
"label": "Other",
"id": 31
}
],
}
]
},
{
"success": true,
"data": [
{
"key": "a4269",
"name": "vegetables",
"options": [
{
"label": "lettuce",
"id": 34
},
{
"label": "cucumber",
"id": 35
},
{
"label": "radish",
"id": 36
}
],
}
]
},
{
"success": true,
"data": [
{
"key": "d76fa",
"name": "pasta",
"options": [
{
"label": "spaghetti",
"id": 54
},
{
"label": "rigatoni",
"id": 55
},
{
"label": "linguine",
"id": 56
},
{
"label": "lasagna",
"id": 60
},
{
"label": "fettuccine",
"id": 61
}
],
}
]
}];
function filteredLabelsAsString(obj_key, obj, content=response) {
// sanity check: obj must contain obj_key
if (Object.keys(obj).includes(obj_key)) {
return content.filter((item) => {
// filter content using value of obj_key
return item.data[0].key == obj_key;
}).map((item) => {
// item : { success: true, data: [] }
// map over options array
return item.data[0].options.map((opt) => {
// option : {id, label}
// return the label if the id is in the obj object's list
if (obj[item.data[0].key].id.includes(opt.id))
return opt.label;
}).filter((label) => {
// filter out empty items
return label !== undefined;
});
}).join(",");
}
// if obj does not contain obj_key return empty string
return "";
}
console.log("fruits: " + filteredLabelsAsString("c4ecb", obj));
console.log("vegetables: " + filteredLabelsAsString("a4269", obj));
console.log("pasta: " + filteredLabelsAsString("d76fa", obj));

Get the object value based on input objects in javascript

I would like to how to get the value based on input objects in javascript.
If the source matches the currency and also matches the type in paymentin and paymentout in object then get the value of speed and fees
for example 'SGD' with type_in 'credit' and type_out 'bank' should return the speed and fee
Expected Output:
id: transfer credit: 1 days 1% pay_in: pay_out: bank
id: insta debit: 1 days 1.5% pay_in: pay_out: bank
I tried but i got stuck
function getValue(source,typein,typeout,obj){
var filterArr = source.filter(function(value){
return value.country_from.filter(function(payin){
const in= payin.paymentIn.filter(function(ty){
return ty.type == typein
})
const out = payin.paymentIn.filter(function(ty){
return ty.type == typeout
})
})
})
}
var result = getValue(source,type_in,type_out,obj);
//input objects
var source="SGD";
var type_in="credit";
var type_out="bank";
var obj = [{
"id": "transfer",
"country_from": [{
"currency": [
"SGD",
"USD"
],
"paymentIn": [{
"type": "credit",
"speed": {
"unit": "days",
"number": "1"
},
"fee": {
"type": "%",
"number": "1"
}
}],
"paymentOut": [{
"type": "bank",
"speed": {
"unit": "days",
"number": "2"
}
}]
}]
}, {
"id": "insta",
"country_from": [{
"currency": [
"SGD",
"USD"
],
"paymentIn": [{
"type": "credit",
"speed": {
"unit": "days",
"number": "1"
},
"fee": {
"type": "%",
"number": "1.5"
}
}],
"paymentOut": [{
"type": "bank",
"speed": {
"unit": "days",
"number": "2"
}
}]
}]
}]
I think you have made some mistakes on your initial code, but I guess it is due to the confusion of dealing with so many layers of objects and arrays. This is what you should do:
const getValue = (source, typein, typeout, obj) => {
const res = obj.map(item => {
if (item['country_from'][0]['paymentIn'][0]['type'] === typein
&& item['country_from'][0]['currency'].includes(source)
&& item['country_from'][0]['paymentOut'][0]['type'] === typeout) {
return `id: ${item['id']} credit: ${item['country_from'][0]['paymentIn'][0]['speed']['number']} days credit: ${item['country_from'][0]['paymentIn'][0]['fee']['number']}${item['country_from'][0]['paymentIn'][0]['fee']['type']} pay_in: pay_out: ${item['country_from'][0]['paymentOut'][0]['speed']['number']}`
}
});
return res;
}
getValue('SGD', 'credit', 'bank', obj);
Basically, I will iterate through every element of the input array, obj (which is the one you posted on your question), and within each iteration, I check for the following 3 conditions using the if statement.
1) The paymentIn type matches typein
2) The paymentOut type matches typein
3) currency contains source
Elements that fulfil the above 3 conditions will the string result.
EDIT: To answer your question on the comments, if the paymentIn array has more than one object, we can use Array.some() to check if the object with the type property has the same value as typeIn.
if (item['country_from'][0]['paymentIn'].some(payment => payment['type']===typein)
&& item['country_from'][0]['currency'].includes(source)
&& item['country_from'][0]['paymentOut'][0]['type'] === typeout) {
// to get the object with that typein
const filteredPaymentIn = item['country_from'][0]['paymentIn'].filter(payment => payment['type']===typein)[0];
}

Javascript test for existence of object key in a object with arrays

I need to check if a property in a complex object (nested objects with arrays) exists or not.
I found several posts on this subject, the most visited the one below.
The problem with the provided solution (checkNested function) doesn't work with objects with arrays.
Does anyone have a solution that cover this case as well?
Cheers.
javascript test for existence of nested object key
This the function I tested:
function checkProperty(obj, prop) {
var parts = prop.split('.');
for (var i = 0, l = parts.length; i < l; i++) {
var part = parts[i];
if (obj !== null && typeof obj === "object" && part in obj) {
obj = obj[part];
} else {
return false;
}
}
return true;
}
This is an example of my object:
{
"_msgid": "3ae30deb.af9962",
"topic": "",
"payload": "I am really upset terrible service",
"error": null,
"parts": {
"id": "3ae30deb.af9962",
"type": "array",
"count": 2,
"len": 1,
"index": 0
},
"case_id": "0001",
"features": {
"usage": {
"text_units": 1,
"text_characters": 34,
"features": 7
},
"sentiment": {
"document": {
"score": -0.912124,
"label": "negative"
}
},
"semantic_roles": [{
"subject": {
"text": "I"
},
"sentence": "I am really upset terrible service",
"object": {
"text": "really upset terrible service",
"keywords": [{
"text": "terrible service"
}]
},
"action": {
"verb": {
"text": "be",
"tense": "present"
},
"text": "am",
"normalized": "be"
}
}],
"language": "en",
"keywords": [{
"text": "terrible service",
"sentiment": {
"score": -0.912124
},
"relevance": 0.902721,
"emotion": {
"sadness": 0.462285,
"joy": 0.002207,
"fear": 0.125395,
"disgust": 0.17766,
"anger": 0.575927
}
}],
"entities": [],
"emotion": {
"document": {
"emotion": {
"sadness": 0.462285,
"joy": 0.002207,
"fear": 0.125395,
"disgust": 0.17766,
"anger": 0.575927
}
}
},
"concepts": [],
"categories": [{
"score": 0.99946,
"label": "/health and fitness/disease/headaches and migraines"
}, {
"score": 0.0155692,
"label": "/education/school"
}, {
"score": 0.0141217,
"label": "/family and parenting/children"
}]
}
}
And a failure test:
console.log(checkProperty(msg, 'features.keywords[0].text') ? msg.features.keywords[0].text : "NA");
The checkProperty function you're using doesn't recognize brackets ([ and ]), it only understands dots. So, just give it dots:
checkProperty(msg, 'features.keywords.0.text');

Validating arrays in an object of arrays in Javascript

I have a query object that looks like this
{
"regions": [],
"countries": [],
"channels": [],
"partners": [],
"branches": [],
"agents": []
}
After populating the arrays in the object it looks like this.
{
"regions": [{
"key": "101",
"value": "Middle East(XX)"
}],
"countries": [],
"channels": [],
"partners": [{
"key": "201",
"value": "Partner A"
}, {
"key": "202",
"value": "Partner B"
}],
"branches": [{
"key": "401",
"value": "Bangalore"
}, {
"key": "402",
"value": "Chennai"
}],
"agents": [{
"key": "501",
"value": "IBM - Metlife"
}]
}
I'm trying to loop through each of these arrays and determine if I should show the filter component. If any of the arrays in the object holds value, I should be showing the filter component
The code:
case false:
let itemsInQuery = 0;
Object.keys(query).forEach((item) => {
itemsInQuery = query[item].length ? itemsInQuery++ : itemsInQuery;
})
itemsInQuery ? this.setState({showBubbles: true, query}) : this.setState({showBubbles: false, query})
break;
I'm not sure what is wrong here, but itemsInQuery is always zero. Also, is there a better way to do this?
Thank you in advance!
If any of the array have items in, you want a boolean to be true?
This sounds like a case for .some which on an array will take a predicate and return true if any item in that array matches the predicate.
const shouldShow = Object.keys(data).some(key => data[key].length > 0)
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/some
The problem is with this:
itemsInQuery = query[item].length ? itemsInQuery++
The ++ postfix operator returns the current value of itemsInQuery to the rest of the expression (i.e. 0) and then increments that variable to 1. But this is nullified by the assignment that happens afterwards to itemsInQuery which is the value 0.
So don't use ++ in an expression.
You can use this += instead:
itemsInQuery += query[item].length ? 1 : 0;
Does this do what you want?
var data1 = {
"regions": [{
"key": "101",
"value": "Middle East(XX)"
}],
"countries": [],
"channels": [],
"partners": [{
"key": "201",
"value": "Partner A"
}, {
"key": "202",
"value": "Partner B"
}],
"branches": [{
"key": "401",
"value": "Bangalore"
}, {
"key": "402",
"value": "Chennai"
}],
"agents": [{
"key": "501",
"value": "IBM - Metlife"
}]
};
var data2 = {
"regions": [],
"countries": [],
"channels": [],
"partners": [],
"branches": [],
"agents": []
}
function hasEntries (data) {
for (var index in data) {
if (Array.isArray(data[index]) && data[index].length) {
return true;
}
}
return false;
}
console.log(hasEntries(data1));
console.log(hasEntries(data2));

Categories