I am implementing a recursive encryption for Javascript objects but the solution I came up with is non-functional. This has caused some weird errors as it manipulates the object directly. Is there any way to make this functional (return a new encypted object)?
I am at a loss on how to make this stay recursive and at the same time return a new object (functional). Specifically this is encryptObject(dd)
class Security {
static encryptText = (text) => {
//function to encrypt text/strings
};
static encryptObject(dd) {
try {
for (let d in dd) {
if (!dd[d]) {
continue;
} else if (typeof dd[d] !== "object") {
dd[d] = this.encryptText(dd[d]);
} else {
this.encryptObject(dd[d]);
}
}
} catch (e) {
console.log(e.message + `error encrypting`);
}
}
const data = {dog:"john", cat:"anders", weapons:{laser:"3",sword:"1"}}
Security.encrypt(data)
I would like to call the function like this instead
const data = {dog:"john", cat:"anders", weapons:{laser:"3",sword:"1"}}
const encryptedData = Security.encrypt(data)
Just create and return a new object instead?
static encryptObject(objectToEncrypt) {
try {
const newObj = {};
for (const [key, value] of Object.entries(objectToEncrypt)) {
if (!value) {
newObj[key] = value;
} else if (typeof value !== "object") {
newObj[key] = this.encryptText(value);
} else {
newObj[key] = this.encryptObject(value);
}
}
return newObj;
} catch (e) {
console.log(e.message + `error encrypting`);
}
}
One way to write this is to base it on a map function which handles arrays and objects. With this, and a simple identity function (x) => x, we can write this as
const encryptObj = (o) =>
(typeof o == 'object' ? map (encryptObj) : typeof o == 'string' ? encryptText : x => x) (o)
Based on whether we have an object, a string, or something else, we choose to either recursively map the result over the children, call the text encryption, or return the value unchanged. Using a simple rot13 function as a dummy text encryption we might write a plain function like this:
const map = (fn) => (o) => Array .isArray (o)
? o .map (fn)
: Object .fromEntries (Object .entries (o) .map (([k, v]) => [k, encryptObj (v)]))
// simple rot13
const encryptText = (cs) => [...cs] .map ((c, i, _, cc = cs.charCodeAt (i)) => cc > 64 && cc <= 91 ? String .fromCharCode (65 + ((cc - 52) % 26)) : cc > 96 && cc <= 123 ? String .fromCharCode (97 + ((cc - 84) % 26)) : c) .join ('')
const encryptObj = (o) =>
(typeof o == 'object' ? map (encryptObj) : typeof o == 'string' ? encryptText : x => x) (o)
console .log (encryptObj ({
a: 'foo',
b: ['bar', 'baz', 'qux'],
c: false,
d: {
e: {
f: {
g: {
h: 42,
i: 'CORGE',
j: {
k: 'Grault'
}
}
},
l: 99
}
}
}))
.as-console-wrapper {max-height: 100% !important; top: 0}
And of course you can make this a static function of your class by sprinkling in some thiss around the code.