search inside object of objects and replace value - javascript

I want to loop through all objects values inside object and replace password value with * Restricted * . I want to use recursive way tp loop over all this items
before i was targeting objects that include password value but was thinking that it can appear somewhere else inside the object entry .
this is what i tried
if (entry.requestBody) {
for (const key of Object.keys(entry.requestBody)) {
if (key.toLowerCase().includes("password")) {
entry.requestBody[key] = "***Restricted***"
}
}
if (entry.config._object) {
for (const key of Object.keys(entry.config._object)) {
if (key.toLowerCase().includes("password")) {
entry.config._object[key] = "***Restricted***"
}
}
}
}
{
"requestBody": {
"email": "ror#ror.com",
"password": "asdasdsad"
},
"code": "VALIDATION_ERROR",
"config": {
"isJoi": true,
"name": "ValidationError",
"details": [
{
"message": "\"email\" must be a valid email",
"path": [
"email"
],
"type": "string.email",
"context": {
"value": "ror#ror.com",
"key": "email",
"label": "email"
}
}
],
"_object": {
"email": "ror#ror.com",
"password": "asdasdsad"
},
"_meta": {
"source": "body"
}
}
}
}
"requestBody": {
"email": "ror#ror.com",
"password": "***Restricted***"
}

Instead of recursion, how about using regex for a quick and dirty solution:
var bodyString = JSON.stringify(entry.requestBody);
var fixedBodyString = bodyString.replace(/"password":".*"/g, '"password":"***Restricted***"');
var body = JSON.parse(fixedBodyString );
Working example:
https://playcode.io/353673?tabs=script.js,preview,console

Related

Group and count values in an array

I have an array with objects, like the following.
b = {
"issues": [{
"fields": {
"status": {
"id": "200",
"name": "Backlog"
}
}
}, {
"fields": {
"status": {
"id": "202",
"name": "close"
}
}
}, {
"fields": {
"status": {
"id": "201",
"name": "close"
}
}
}]
};
I want to count how many issues have status close, and how many have backlog. I'd like to save the count in a new array as follows.
a = [
{Name: 'Backlog', count: 1},
{Name: 'close', count: 2}
];
I have tried the following.
b.issues.forEach(function(i) {
var statusName = i.fields.status.name;
if (statusName in a.Name) {
a.count = +1;
} else {
a.push({
Name: statusName,
count: 1
});
}
});
That however doesn't seem to be working. How should I implement this?
This is a perfect opportunity to use Array#reduce. That function will take a function that is applied to all elements of the array in order and can be used to accumulate a value. We can use it to accumulate an object with the various counts in it.
To make things easy, we track the counts in an object as simply {name: count, otherName: otherCount}. For every element, we check if we already have an entry for name. If not, create one with count 0. Otherwise, increment the count. After the reduce, we can map the array of keys, stored as keys of the object, to be in the format described in the question. See below.
var b = {
"issues": [{
"fields": {
"status": {
"id": "200",
"name": "Backlog"
}
}
}, {
"fields": {
"status": {
"id": "202",
"name": "close"
}
}
}, {
"fields": {
"status": {
"id": "201",
"name": "close"
}
}
}]
};
var counts = b.issues.reduce((p, c) => {
var name = c.fields.status.name;
if (!p.hasOwnProperty(name)) {
p[name] = 0;
}
p[name]++;
return p;
}, {});
console.log(counts);
var countsExtended = Object.keys(counts).map(k => {
return {name: k, count: counts[k]}; });
console.log(countsExtended);
.as-console-wrapper {
max-height: 100% !important;
}
Notes.
Array#reduce does not modify the original array.
You can easily modify the function passed to reduce to for example not distinguish between Backlog and backlog by changing
var name = c.fields.status.name;
into
var name = c.fields.status.name.toLowerCase();
for example. More advanced functionality can also easily be implemented.
Using ES6 Arrow functions you can do it with minimum syntax
var b = {
"issues": [{
"fields": {
"status": {
"id": "200",
"name": "Backlog"
}
}
}, {
"fields": {
"status": {
"id": "202",
"name": "close"
}
}
}, {
"fields": {
"status": {
"id": "201",
"name": "close"
}
}
}]
};
var countOfBackLog = b.issues.filter(x => {
return x.fields.status.name === "Backlog"
}).length
var countOfClose = b.issues.filter(x => {
return x.fields.status.name === "close"
}).length
a =[{Name: 'Backlog', count : countOfBackLog}, {Name: 'close', count : countOfClose}]
More about arrow functions here
You can write like this. It is dynamic.
var a = {};
for(var key in b["issues"]){
if(!a.hasOwnProperty(b["issues"][key].fields.status.name)){
a[b["issues"][key].fields.status.name] = 1;
}else{
a[b["issues"][key].fields.status.name] = a[b["issues"][key].fields.status.name]+1;
}
}
var c = [];
for(var key1 in a){
c.push({
name : key1,
count : a[key1]
});
}
Something like this should do the trick. Simply iterate over your data, keep 2 counters with the number of each type of issue, and create the data format you want in the end. Try it live on jsfiddle.
var b = {
"issues": [{
"fields": {
"status": {
"id": "200",
"name": "Backlog"
}
}
}, {
"fields": {
"status": {
"id": "202",
"name": "close"
}
}
}, {
"fields": {
"status": {
"id": "201",
"name": "close"
}
}
}]
};
var data = [];
for(var issue of b.issues){
var entryFound = false;
var tempObj = {
name: issue.fields.status.name,
count: 1
};
for(var item of data){
if(item.name === tempObj.name){
item.count++;
entryFound = true;
break;
}
}
if(!entryFound){
data.push(tempObj);
}
}
console.log(data);

How to iterate through deeply nested objects inside of a JSON?

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;
}

Accessing second array in a JSON decode using Jquery

I need to access the second array from a JSON decoded string, but I am having no luck.
The entire JSON string is displayed in var RAW00, and then split into var RAW01 & var RAW02.
All 3 of these are for testing - RAW00 is identical to msg
When they are split - I can access either, depending on what variable I start of with, but when I use RAW00 I cannot access the tutor section.
I will provide more detail if required, but my question is:
How do I see and access the tutor array in the second $.each (nested) block??]
Thanks :-)
success: function(msg)
{
var test = "";
var raw00 = {
"allData": [
{
"class2": [
{
"tid": "1",
"name": "Monday 2"
},
{
"tid": "1",
"name": "Monday Test"
}
]
},
{
"tutor": [
{
"fname": "Jeffrey",
"lname": "Kranenburg"
},
{
"fname": "Jeffrey",
"lname": "Kranenburg"
}
]
}
]
};
var raw01 = {
"allData": [
{
"class2": [
{
"tid": "1",
"name": "Monday 2"
},
{
"tid": "1",
"name": "Monday Test"
}
]
}
]
};
var raw02 = {
"allData": [
{
"tutor": [
{
"fname": "Jeffrey",
"lname": "Kranenburg"
},
{
"fname": "Jeffrey",
"lname": "Kranenburg"
}
]
}
]
};
$.each(raw00.allData, function(index, entry)
{
$.each(entry.class2, function (index, data)
{
console.log(this.name);
test += '<tr><td>'+this.name+'</td>';
});
$.each(entry.tutor, function (index, data)
{
console.log(this.fname);
test += '<td>'+this.name+'</td></tr>';
});
$('#all-courses-table-content').html( test );
});
You need to check whether the current element of the array is an object with class2 property or tutor property.
$.each(raw00.allData, function(index, entry) {
if (entry.hasOwnProperty('class2')) {
$.each(entry.class2, function (index, data)
{
console.log(this.name);
test += '<tr><td>'+this.name+'</td>';
});
}
if (entry.hasOwnProperty('tutor')) {
$.each(entry.tutor, function (index, data)
{
console.log(this.fname);
test += '<td>'+this.fname+'</td></tr>';
});
}
$('#all-courses-table-content').html( test );
});
Things would probably be simpler if you redesigned the data structure. It generally doesn't make sense to have an array of objects when each object just has a single key and it's different for each. I suggest you replace the allData array with a single object, like this:
var raw00 = {
"allData": {
"class2": [
{
"tid": "1",
"name": "Monday 2"
},
{
"tid": "1",
"name": "Monday Test"
}
],
"tutor": [
{
"fname": "Jeffrey",
"lname": "Kranenburg"
},
{
"fname": "Jeffrey",
"lname": "Kranenburg"
}
]
}
};

Javascript passing variables

Okay so, I'm trying to get the facebook name and email of a user (succeed in that), and then use mandrill to email me that info. But for some reason, can't seem to get the name and email address to pass into the params object. (I deleted a lot of the facebook login stuff to make it clearer) Help!!
$(function() {
function getCurrentUserInfo() {
FB.api('/me', function(userInfo) {
console.log(userInfo.name + ': ' + userInfo.email);
temp = userInfo.email;
name = userInfo.name;
var needed = {
"name": userInfo.name,
"email": userInfo.email
}
function log(obj) {
$('#response').text(JSON.stringify(obj));
}
var m = new mandrill.Mandrill('key');
// create a variable for the API call parameters
var params = {
"message": {
"from_email":"emailf",
"to":[{"email":"emailg"}],
"subject": "New email",
"html": "*|NAME|* has the email *|EMAIL|* ",
"autotext": "true",
"track_opens": "true",
"track_clicks": "true",
"merge_vars": [
{
"rcpt": "emailrep",
"vars": [
{
"name": "NAME",
"content": "needed["name"]"
},
{
"name": "EMAIL",
"content": "needed["email"]"
}
]
}
]
}
};
You're passing strings when you need the variable:
"vars": [
{
"name": "NAME",
"content":needed["name"]
},
{
"name": "EMAIL",
"content": needed["email"]
}
]

Finding child object using one of its properties in JSON

I am trying to find a child object in JSON by one of its properties and add more properties to that object. I am not sure how to do this using JQuery (or regular javascript). For example: From the following JSON, I would like to find a category with id 123-1 and then add another category object as a child object. Thanks for your help.
JSON:
{
"result": {
"category":
{
"id": 123,
"name": "cat1",
"rules": [
{
"rulename": "r1",
"regex": ""
},
{
"rulename": "r2",
"regex": ""
}
],
"category":
{
"id": "123-1",
"name": "cat1-1",
"rules": [
{
"rulename": "r1-1",
"regex": ""
}
]
}
}
}
}
Javascript:
function addSubCategory(catId, anotherCatObj) {
//Step1: Find category object with catID in the existing json
//Step3: add the supplied object as a child.
}
function appendCategoryTo(categories, destinationCategoryId, newCategoryToAdd){
var success = false;
for (var i = 0; i < categories.length && !success; i++){
var category = categories[i];
if (category.id == destinationCategoryId){
category.category = category.category || [];
success = !!category.category.push(newCategoryToAdd);
} else if (category.category) {
success = appendCategoryTo(category.category, destinationCategoryId, newCategoryToAdd);
}
}
return success;
}
you have to start at the obj.result.category node in order to take advantage of the recursive ability, but you can easily wrap that method in another that makes it more polite.
but, as-is, here's an example usage:
appendCategoryTo(o.result.category, '123-1', {
id: '123-1-1',
name: 'cat-1-1-1',
rules: []
});
console.log(JSON.stringify(o));
Which adds a new category property to the nested category as an array (i assume this follows the nomenclature) then adds the element to that new array--thus giving you:
{
"result": {
"category": [
{
"id": 123,
"name": "cat1",
"rules": [
{
"rulename": "r1",
"regex": ""
},
{
"rulename": "r2",
"regex": ""
}
],
"category": [
{
"id": "123-1",
"name": "cat1-1",
"rules": [
{
"rulename": "r1-1",
"regex": ""
}
],
"category": [ // BEGIN new addition
{
"id": "123-1-1",
"name": "cat-1-1-1",
"rules": [
]
}
] // END new addition
}
]
}
]
}
}
Example to play with on jsfiddle, btw: http://jsfiddle.net/cqRzX/

Categories

Resources