Related
I want to compare 2 json and return error message for which object or value is not match
For example:
json1 = {
"id": 1,
"product": {
"productId": "456",
"product_detail": [
{
"name": {
"value": 1
}
},
{
"name": {
"value": 2
}
}
]
}
}
json2 = {
"id": 1,
"product": {
"productId": "123",
"product_info": [
{
"name": [{
"value": 3,
}
},
{
"name": {
"value": 4
}
}
]
}
}
I was using try / catch on each object and value, however, it is complicated process to const each propriety. Therefore, i am looking for another way to do the checking
My expected error message result should return all object / value is not matching in test result:
Failed - json2 > product_info propriety not matching with json
Failed - json2 > product.product_detail.name[0].value : 3 not equal with json1 > product.product_detail.name[0].value :1
Failed - json2 > product.product_detail.name[1].value : 4 not equal with json1 > product.product_detail.name[1].value :2
If there are no error found > return message pass
are you sure you need recursion for that?
Checkout lodash isEqual function: https://lodash.com/docs/#isEqual
I'm importing data from my crm Pipedrive into Google sheets using Google Apps Script. This is part of a larger process but I'm at an impasse with this section of the script. I need to return a value by matching two parts of one array to another array.
First I pull all deal fields, which returns custom field keys and their id/label pairs. Here's a simplified output example:
{
"success": true,
"data": [
{
"id": 12500,
"key": "c4ecbe01c34994ede3a50c0f8",
"name": "Lead Type",
"options": [
{
"label": "Expired",
"id": 28
},
{
"label": "Sale",
"id": 29
},
{
"label": "Rent",
"id": 30
},
{
"label": "Other",
"id": 31
}
],
"mandatory_flag": false
}
]
}
Then I have separate info from a specific deal that includes an id. I need to match the below id 28 to the above array and return the label Expired:
var leadType = dealresponse.data["c4ecbe01c34994ede3a50c0f8"];
which returns 28
I don't know what '28' means so that's why I need to match it to the label Expired.
The dealFields array is long, maybe 50 or 100 of the above array objects. And there are around 10 custom deal field keys where I will have to return the label base on matching the key and id. I think I have to loop each key and id to return the label. But not sure of the optimum way to do this and save on processing power.
I tried:
for (var i in dealFieldsresponse) {
if (dealFieldsresponse[i].data.key == "c4ecbe01c34994ede3a50c0f8") {
for (var j in dealFieldsresponse[j]) {
if (dealFieldsresponse[j].id == "28") {
Logger.log(dealFieldsresponse[j].label);
}
}
}
}
It's not working. I'm new at javascript and programming in general so this is my best guess and I appreciate any insights.
Edit: here's a bigger chunk of code that I have to work with:
// Get deal fields data
var dealFieldsurl = URL +'/v1/dealFields?api_token='+ API_TOKEN;
var options = {
"method": "get",
"contentType": "application/json",
};
var dealFieldsresponse = UrlFetchApp.fetch(dealFieldsurl, options);
dealFieldsresponse = JSON.parse(dealFieldsresponse.getContentText());
// Get deal data
var dealurl = URL +'/v1/deals/' + dealId + '?api_token='+ API_TOKEN;
var options = {
"method": "get",
"contentType": "application/json",
};
var dealresponse = UrlFetchApp.fetch(dealurl, options);
dealresponse = JSON.parse(dealresponse.getContentText());
var propertyAddress = dealresponse.data["9bd1d8c4f07f5795fd8bffb16f3b63c6547d7d3a"];
var leadType = dealresponse.data["c4ecbe01c3494d1be52432f4a3194ede3a50c0f8"];
var dealType = dealresponse.data["a4269fb4730cf7fd1787752be94eacbc4b0de24e"];
var dealSource = dealresponse.data["d76fa2d6f8454a51f7d64d981cd9320877bc2ea0"];
var marketingFor = dealresponse.data["58cb55090b55652b7f89a8b44074682d874c548a"];
var dateListedOnMarket = dealresponse.data["aa49c7b95a7d151bec4c2d936f6ab40d0caea43c"];
var dateTakenOffMarket = dealresponse.data["660c1250b0a641a10ff9121c2df124ff89c13052"];
var askingPrice = dealresponse.data["1de94dbf589fda7a3a3248662cd24f03d512a961"];
And the dealFieldsresponse variable stores an array with many objects containing arrays. Here are two primary objects, as you can see each has a key and then options. I need to match the key and then find the id within options for each key
{
"id": 12500,
"key": "c4ecbe01c3494d1be52432f4a3194ede3a50c0f8",
"name": "Lead Type",
"order_nr": 64,
"field_type": "set",
"add_time": "2020-08-20 19:33:22",
"update_time": "2020-08-20 19:33:22",
"last_updated_by_user_id": 11678191,
"active_flag": true,
"edit_flag": true,
"index_visible_flag": true,
"details_visible_flag": true,
"add_visible_flag": true,
"important_flag": true,
"bulk_edit_allowed": true,
"searchable_flag": false,
"filtering_allowed": true,
"sortable_flag": true,
"options": [
{
"label": "Expired",
"id": 28
},
{
"label": "Sale",
"id": 29
},
{
"label": "Rent",
"id": 30
},
{
"label": "Other",
"id": 31
}
],
"mandatory_flag": false
},
{
"id": 12502,
"key": "a4269fb4730cf7fd1787752be94eacbc4b0de24e",
"name": "Deal Type",
"order_nr": 65,
"field_type": "set",
"add_time": "2020-08-20 19:57:12",
"update_time": "2020-08-20 19:57:12",
"last_updated_by_user_id": 11678191,
"active_flag": true,
"edit_flag": true,
"index_visible_flag": true,
"details_visible_flag": true,
"add_visible_flag": true,
"important_flag": true,
"bulk_edit_allowed": true,
"searchable_flag": false,
"filtering_allowed": true,
"sortable_flag": true,
"options": [
{
"label": "Lease",
"id": 37
},
{
"label": "Financing",
"id": 38
},
{
"label": "Assign",
"id": 39
},
{
"label": "ST",
"id": 40
},
{
"label": "Other (see notes)",
"id": 41
}
],
"mandatory_flag": false
},
Edit 2: how do I return the labels for multiple ids?
const obj = {
"a4269fb4730cf7fd1787752be94eacbc4b0de24e": {id: 37,38}, "58cb55090b55652b7f89a8b44074682d874c548a": {id: 44,45},
"2ec54cce0d091b69b1fd1a245c7aad02b57cadb8": {id: 126},
"fab84c732295022ecd7bdf58892a62cb4d8ecf24": {id: 50,52,54},
};
For example, I'd want the first to return red, blue as a string, and the second to return green, orange as a string. Assuming the labels that match the ids are colors. The third one only has one id, but the fourth one has three. How do I account for this? And I'd like my output to be some kind of array where I can then say search key a4269fb4730cf7fd1787752be94eacbc4b0de24e and return value red, blue as a string
I believe your goal as follows.
You want to retrieve the value of label using key and id from the JSON object in your question using Google Apps Script.
As a sample situation, you want to retrieve the value of "label": "Expired" using "key": "c4ecbe01c34994ede3a50c0f8" and "id": 28.
The JSON object has the arrays of data and options. Both arrays have the several elements.
Modification points:
If dealFieldsresponse is the JSON object in your question, dealFieldsresponse.data and dealFieldsresponse.data[].options are 1 dimensional array. When you want to retrieve the value of key and id, it is required to loop those arrays.
When above points are reflected to your script, it becomes as follows.
Modified script:
const searchKey = "c4ecbe01c34994ede3a50c0f8"; // Please set the value of key.
const searchId = 28; // Please set the value of id.
const dealFieldsresponse = {
"success": true,
"data": [
{
"id": 12500,
"key": "c4ecbe01c34994ede3a50c0f8",
"name": "Lead Type",
"options": [
{
"label": "Expired",
"id": 28
},
{
"label": "FSBO",
"id": 29
},
{
"label": "FRBO",
"id": 30
},
{
"label": "Other",
"id": 31
}
],
"mandatory_flag": false
}
]
};
const data = dealFieldsresponse.data;
for (let i = 0; i < data.length; i++) {
if (data[i].key == searchKey) {
const options = data[i].options;
for (let j = 0; j < options.length; j++) {
if (options[j].id.toString() == searchId.toString()) {
// Logger.log(options[j].label);
console.log(options[j].label);
}
}
}
}
Other sample:
As other sample script, how about the following script? In this sample, the result values are put in an array.
const searchKey = "c4ecbe01c34994ede3a50c0f8"; // Please set the value of key.
const searchId = 28; // Please set the value of id.
const dealFieldsresponse = {
"success": true,
"data": [
{
"id": 12500,
"key": "c4ecbe01c34994ede3a50c0f8",
"name": "Lead Type",
"options": [
{
"label": "Expired",
"id": 28
},
{
"label": "FSBO",
"id": 29
},
{
"label": "FRBO",
"id": 30
},
{
"label": "Other",
"id": 31
}
],
"mandatory_flag": false
}
]
};
const res = dealFieldsresponse.data.reduce((ar, {key, options}) => {
if (key == searchKey) {
options.forEach(({id, label}) => {
if (id == searchId) ar.push(label);
});
}
return ar;
}, []);
console.log(res)
Added:
When you want to retrieve the multiple values using the multiple key and id, how about the following sample script? In this sample script, the key c4ecbe01c34994ede3a50c0f8 and id 28 and the key a4269fb4730cf7fd1787752be94eacbc4b0de24e and id 37 are searched and the values of label are retrieved.
const obj = {
"c4ecbe01c34994ede3a50c0f8": {id: 28},
"a4269fb4730cf7fd1787752be94eacbc4b0de24e": {id: 37}
}; // Please set the key and id you want to search.
const dealFieldsresponse = {
"success": true,
"data": [
{
"id": 12500,
"key": "c4ecbe01c34994ede3a50c0f8",
"name": "Lead Type",
"options": [
{
"label": "Expired",
"id": 28
},
{
"label": "FSBO",
"id": 29
},
{
"label": "FRBO",
"id": 30
},
{
"label": "Other",
"id": 31
}
],
"mandatory_flag": false
}
]
};
dealFieldsresponse.data.forEach(({key, options}) => {
if (obj[key]) {
options.forEach(({id, label}) => {
if (id == obj[key].id) obj[key].label = label;
});
}
});
console.log(obj)
Result:
When above script is run, the following result is obtained.
{
"c4ecbe01c34994ede3a50c0f8":{"id":28,"label":"Expired"},
"a4269fb4730cf7fd1787752be94eacbc4b0de24e":{"id":37}
}
At above sample JSON object, the label of the key c4ecbe01c34994ede3a50c0f8 and id 28 is retrieved.
I have this data from a csv file that i have to use in a dependant dropdown with jquery. I can't figure out if it is possible to nest the data i received for what i already have coded.
CSV file
Banco Tarjeta Cuotas Medio_Pago Coeficiente TEA CFT
Santander Visa 1 modulodepago2 1 0.00% 0.00%
Santander Visa 1 nps 1.0262 18.56% 22.84%
Frances Visa 1 modulodepago2 1 0.00% 0.00%
Frances Master 2 nps 1.0262 18.56% 22.84%
My json data comes like this
[{"banco":"Santander","tarjeta":"Visa","cuotas":"1","medio_pago":"modulodepago2",
"coeficiente":"1","tea":"0.00%","cft":"0.00%"},
{"banco":"Santander","tarjeta":"Visa","cuotas":"1","medio_pago":"nps",
"coeficiente":"1.0262","tea":"18.56%","cft":"22.84%"} ...
etc...
Is there a way i can nest this json data like this (+ adding unique names and id's)?
var myJson = {
"banco": [
{
"name": "Santander",
"id": "Santander",
"tarjeta": [
{
"name": "Visa",
"id": "SantanderVisa",
"cuotas": [
{
"name": "1",
"id": "SantanderVisa1",
"medio_pago": "modulodepago2"
"coeficiente": "1",
"tea": "0.00%",
"cft": "0.00%",
},
{
"name": "1",
"id": "SantanderVisa2",
"medio_pago": "nps"
"coeficiente": "1.0262",
"tea": "18.56%",
"cft": "22.84%",
}
]
}
]
},
{
"name": "Frances",
"id": "Frances",
"tarjeta": [
{
"name": "Visa",
"id": "FrancesVisa",
"cuotas": [
{
"name": "1",
"id": "FrancesVisa1",
"medio_pago": "modulodepago2"
"coeficiente": "1",
"tea": "0.00%",
"cft": "0.00%",
}
]
},
{
"name": "Master",
"id": "FrancesMaster",
"cuotas": [
{
"name": "2",
"id": "FrancesMaster2",
"medio_pago": "nps"
"coeficiente": "1.0262",
"tea": "18.56%",
"cft": "22.84%",
}
]
}
]
}
]
}
You will need to group by keys. An easy way to do this is to use Lodash or Underscore.js.
I used Papa Parse to convert the CSV data into JSON.
var csvData = $('#csv-data').text().trim();
var jsonData = Papa.parse(csvData, { delimiter:',', header:true }).data;
var transformedJson = {
banco : _.chain(jsonData)
.groupBy('Banco')
.toPairs()
.map(banco => {
return {
name : banco[0],
id: banco[0],
tarjeta : _.chain(banco[1])
.groupBy('Tarjeta')
.toPairs()
.map(tarjeta => {
return {
name: tarjeta[0],
id: banco[0] + tarjeta[0],
cuotas: _.map(tarjeta[1], cuota => {
return {
name: cuota['Cuotas'],
id: banco[0] + tarjeta[0] + cuota['Cuotas'],
medio_pago: cuota['Medio_Pago'],
coeficiente: cuota['Coeficiente'],
tea: cuota['TEA'],
cft: cuota['CFT']
}
})
};
})
}
}).value()
}
console.log(JSON.stringify(transformedJson, null, 2));
.as-console-wrapper { top: 0; max-height: 100% !important; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/PapaParse/4.1.4/papaparse.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
<textarea id="csv-data" style="display:none" rows="5" cols="72">
Banco,Tarjeta,Cuotas,Medio_Pago,Coeficiente,TEA,CFT
Santander,Visa,1,modulodepago2,1,0.00%,0.00%
Santander,Visa,1,nps,1.0262,18.56%,22.84%
Frances,Visa,1,modulodepago2,1,0.00%,0.00%
Frances,Master,2,nps,1.0262,18.56%,22.84%
</textarea>
try something like this
you get all medio_pago for the others objects you just use the object name.
I haven't tested it but I'm sure this will work for you.
var Json = ...
$.each(Json, function(i, item) {
alert(myJson[i].banco.tarjeta.cuotas.medio_pago);
});
I know there are plenty of questions about iterating through JSON objects but I haven't found one that quite relates to my exact problem. This is the JSON that I'm trying to iterate through:
psinsights = {
"kind": "pagespeedonline#result",
"id": "/speed/pagespeed",
"responseCode": 200,
"title": "PageSpeed Home",
"score": 90,
"pageStats": {
"numberResources": 22,
"numberHosts": 7,
"totalRequestBytes": "2761",
"numberStaticResources": 16,
"htmlResponseBytes": "91981",
"cssResponseBytes": "37728",
"imageResponseBytes": "13909",
"javascriptResponseBytes": "247214",
"otherResponseBytes": "8804",
"numberJsResources": 6,
"numberCssResources": 2
},
"formattedResults": {
"locale": "en_US",
"ruleResults": {
"AvoidBadRequests": {
"localizedRuleName": "Avoid bad requests",
"ruleImpact": 0.0
},
"MinifyJavaScript": {
"localizedRuleName": "Minify JavaScript",
"ruleImpact": 0.1417,
"urlBlocks": [
{
"header": {
"format": "Minifying the following JavaScript resources could reduce their size by $1 ($2% reduction).",
"args": [
{
"type": "BYTES",
"value": "1.3KiB"
},
{
"type": "INT_LITERAL",
"value": "0"
}
]
},
"urls": [
{
"result": {
"format": "Minifying $1 could save $2 ($3% reduction).",
"args": [
{
"type": "URL",
"value": "http://code.google.com/js/codesite_tail.pack.04102009.js"
},
{
"type": "BYTES",
"value": "717B"
},
{
"type": "INT_LITERAL",
"value": "1"
}
]
}
},
{
"result": {
"format": "Minifying $1 could save $2 ($3% reduction).",
"args": [
{
"type": "URL",
"value": "http://www.gmodules.com/ig/proxy?url\u003dhttp%3A%2F%2Fjqueryjs.googlecode.com%2Ffiles%2Fjquery-1.2.6.min.js"
},
{
"type": "BYTES",
"value": "258B"
},
{
"type": "INT_LITERAL",
"value": "0"
}
]
}
}
]
}
]
},
"SpriteImages": {
"localizedRuleName": "Combine images into CSS sprites",
"ruleImpact": 0.0
}
}
},
"version": {
"major": 1,
"minor": 11
}
};
Now, I'm trying to write a function that iterates through all of the ruleResults objects and returns an array of the localizedRuleName properties. According to the JSON, ruleResults has three member objects (AvoidBadRequests, MinifyJavaScript, and SpriteImages). Each of these has a localizedRuleName property I'm trying to access, but when I print out my array, it's blank. Here's how I've written my function:
function ruleList(results) {
var ruleArray = [];
for(var ruleName in results.formattedResults.ruleResults){
ruleArray[counter] = results.formattedResults.ruleResults[ruleName].localizedRuleName;
}
return ruleArray;
}
console.log(ruleList(psinsights));
Can you guys help me get on the right track? I used basically this same method to iterate through the pageStats of the JSON and it worked perfectly. I'm not sure why I can't get it to work with these deeper nested objects and properties.
your problem is not your iteration, but your undefined variable "counter".
Instead of using a counter can use the "push" function:
function ruleList(results) {
var ruleArray = [];
for(var ruleName in results.formattedResults.ruleResults){
ruleArray.push(results.formattedResults.ruleResults[ruleName].localizedRuleName);
}
return ruleArray;
}
fiddle: https://jsfiddle.net/fo9h56gh/
Hope this helps.
you're probably getting a javascript error since counter is not defined. you can try this:
function ruleList(results) {
var ruleArray = [];
var counter = 0;
for(var ruleName in results.formattedResults.ruleResults){
ruleArray[counter] = results.formattedResults.ruleResults[ruleName].localizedRuleName;
counter++;
}
return ruleArray;
}
I have got the following array of Usernames
Usernames = [
{
"id": 1,
"userName": "Jack",
"description": "jack is a nice guy",
"userRoleIds": [
1
]
},
{
"id": 2,
"userName": "Caroline",
"description": "Good girl",
"userRoleIds": [
2,3
]
},
{
"id": 3,
"userName": "Smith",
"description": "Smithyyyy",
"userRoleIds": [
1,2
]
}
]
And an array of userRoles.
userRoles = [
{
id: 1,
roleName: "Admin"
},
{
id: 2,
roleName: "Tester"
},
{
id: 3,
roleName: "Developer"
}
]
What i want to get done is first concat the arrays in in Usernames and userRoles to get the following result.
Usernames = [
{
"id": 1,
"userName": "Jack",
"description": "jack is a nice guy",
"userRoleIds": [
{
"id": 1,
"roleName" : "Admin"
}
]
},
{
"id": 2,
"userName": "Caroline",
"description": "Good girl",
"userRoleIds": [
{
"id": 2,
"roleName" : "Tester"
},
{
"id": 3,
"roleName" : "Developer"
}
]
},...
The second thing i want is to be able to filter for the roleName and userName seperated by pipe signs. As in type something in a text box that searches for userName and roleName for example.
if i type
Caroline, Tester
The result will be
result = [
{
"id": 2,
"userName": "Caroline",
"description": "Good girl",
"userRoleIds": [
2,3
]
},
{
"id": 3,
"userName": "Smith",
"description": "Smithyyyy",
"userRoleIds": [
1,2
]
}
]
What is the best practice for achieving this?
Thanks
Here is how I would do it. I prefer using services and take advantage of their functions to keep code clean.
app.service('UserService', function (PermisionsServices) {
var self = {
'list': [],
'load': function (Users) {//Pass your array of Users
angular.forEach(Users, function (user) {
angular.forEach(user.userRoleIds, function (role) {
self.user.userRolesIds.push(PermisionsServices.get(role));
});
self.list.push(user);
});
}, 'get': function (id) {
for (var i = 0; i < self.list.length; i++) {
var obj = self.list[i];
if (obj.id == id) {
return obj;
}
}
}
};
return self;
});
app.service('PermisionsServices', function () {
var self = {
'list': [],
'load': function (permisions) {//Pass your array of permisions
angular.forEach(permisions, function (permision) {
self.list.push(permision);
});
}, 'get': function (id) {
for (var i = 0; i < self.list.length; i++) {
var obj = self.list[i];
if (obj.id == id) {
return obj;
}
}
}
};
return self;
});
Afterwards, you can use it on your controller:
$scope.users=UserService;
And access each of the users as a separate object which can have multiple object permisions.
NOTE: Building the service (populating it) will of course depend on your app logic and controller, you could just easily remove the "load" function and just hardcode the list object by copy and pasting your arrays.
This is the approach I use to load data from API via resource.
Regards
Edit:
For use on the UI, you would just call:
<div ng-repeat='user in users.list'>
{{user.name}} has {{user.permissions}}
</div>
as the object information is already contained within it.
Edit 2:
If you want to search your data, then you can just add a filter like this:
<div ng-repeat='user in users.list | filter: filterList'>
{{user.name}} has {{user.permissions}}
</div>
And then on the controller:
$scope.filterList = function (user) {
if ($scope.filterTextBox) {
return user.name.indexOf($scope.filterTextBox) == 0;
}
return true;
}
Hope this works for you
I would do with pure JS like this. It won't take more than a single assignment line each.
var Usernames = [
{
"id": 1,
"userName": "Jack",
"description": "jack is a nice guy",
"userRoleIds": [
1
]
},
{
"id": 2,
"userName": "Caroline",
"description": "Good girl",
"userRoleIds": [
2,3
]
},
{
"id": 3,
"userName": "Smith",
"description": "Smithyyyy",
"userRoleIds": [
1,2
]
}
],
userRoles = [
{
id: 1,
roleName: "Admin"
},
{
id: 2,
roleName: "Tester"
},
{
id: 3,
roleName: "Developer"
}
],
modified = Usernames.reduce((p,c) => (c.userRoleIds = c.userRoleIds.map(e => e = userRoles.find(f => f.id == e)),p.concat(c)),[]),
query = ["Caroline","Tester"],
filtered = modified.filter(f => query.includes(f.userName) || f.userRoleIds.some(e => query.includes(e.roleName)));
console.log(JSON.stringify(modified,null,2));
console.log(JSON.stringify(filtered,null,2));
You can use lodash to achieve this.
var role = _.find(userRoles, function(role) {
return role.roleName == 'Tester';
});
_.find(Usernames, function(user) {
return user.userName == 'Caroline' || _.indexOf(user.userRoleIds, role.id)>=0;
});