I have an object like:
obj = {"a": 1, "b": 2, c: 3}
this object is returned by a Node.js package.
I want to pass this object to a request headers but it fails because c in that object has invalid key name I guess.
Is it possible to convert all the key names of my object to strings?
You can use JSON.stringify() to convert it to a valid JSON string:
obj = JSON.stringify({"a": 1, "b": 2, c: 3});
console.log(obj)
You can create a new object and call toString() while creating the key
const obj = {
"a": 1,
"b": 2,
c: 3
};
const newObj = {};
for (let keys in obj) {
newObj[keys.toString()]: obj[keys]
}
In JavaScript, all object keys that are not symbols are converted to strings.
obj = {1: 1}
obj['1'] = 2;
// obj is {1: 2}
If you got such an 'object' from node package it means the data has not been prepared correctly - probably somebody has created JSON by hand (writing a string instead of stringify an object).
If you want to add " to all keys and change an object to a string, so, in other words, make a JSON out of it - you can use JSON.stringify(obj) //"{"a":1,"b":2,"c":3}"
If you want to make an object out of such a broken JSON:
JSON.parse(JSON.stringify(obj)) // "{a: 1, b: 2, c: 3}"
Related
i got two noob questions about destructure an array:
1st question: when destructuring an object, I can define a new value or a new key or both. On array, can I add a new value without add a new key?
const obj = {a: undefined, b:2};
const {a = 3, b} = obj;
console.log(a); // 3
I want to know if there is a version of this but with array instead.
2nd question: is it possible to do not provide a default value for objects? Considering that I think that it is not possible to change default values using destructure.
const obj = [1, {a: 1, b:2}, 3, 4];
const [, object, three, four] = obj;
console.log(object); //{a: 1, b:2}
In this example, object returns {a: 1, b:2} but I wanted it change the value instead. Is that possible?
thanks, regards.
You are confusing default values with mutation of values, and assignment of values to variables with mutation of objects. Below is a demo of the default value feature of destructuring, with comments to explain the behavior.
You will see here that in general, destructuring is not designed for mutation of objects, but for extraction of variables and values. And hopefully also get a feel for why it would be undesirable for mutation to be mixed in to it, even if it were possible.
const obj = [1, {a: 1, b:2, 99:'z'}, ,3, 4, {mutateme: 1}];
const [, {a=3,b=4,c=5}, object={a:7,b:7},three, four, object2] = obj;
// a prop has value=1, b has value=2, c is not defined use default value 5
console.log(a,b,c,object);
//object is empty use default value={a:7,b:7}
// obj is unchanged
console.log(obj)
// mutate object2={mutateme:1} by reference (like a pointer)
object2.mutateme=7
// {mutateme: 1=>7}
console.log(obj)
// example of how you could (sort of) mutate inside a destructuring statement
// computed property, obj[1]=obj[3]=99 returns 99,
// so extract property 99 to variable z and mutate object obj at index [1] and [3] to =99
// y will 99 now.
const [y1, {[obj[1]=obj[3]=99]:z},, y2 ] = obj
console.log(y1, z, y2)
// if something similar were built into destructuring syntax,
// can you imagine how confusing it could get, and cause of all kinds of unexpected behavior?
How can I convert an Object to a string so that output is something like this:
e.g. let a = {b: "c"}
Let's assume the above example is our sample Object. Now we can use JSON.stringify(a) to convert it to string but that outputs,
console.log(a) -> {"b": "c"} but I want something like this: {b: "c"} in the original Object format.
You can try using a Reg-ex, where you replace only the first occurrence of "" with white space character using $1 in the String.prototype.replace call:
const a = JSON.stringify({a: "a", b: "b", c: "c"}).replace(/"(\w+)"\s*:/g, '$1:');
console.log(a);
This code is taken from this answer.
There is a regex solution that is simpler but it has a shortcoming that is inherent to regex. For some edge cases in complex and nested objects it does not work.
const data = {a: "b", "b": "c",
c: {a: "b", "c": "d"}}
console.log(stringify(data))
function stringify(obj_from_json){
if(typeof obj_from_json !== "object" || Array.isArray(obj_from_json)){
// not an object, stringify using native function
return JSON.stringify(obj_from_json);
}
// Implements recursive object serialization according to JSON spec
// but without quotes around the keys.
let props = Object
.keys(obj_from_json)
.map(key => `${key}:${stringify(obj_from_json[key])}`)
.join(",");
return `{${props}}`;
}
You can try javascript-stringify npm package.
I just found {....0} in friend's code. Evaluating it in console returns {} (empty object).
Why is that? What is the meaning of 4 dots in JavaScript?
Four dots actually have no meaning. ... is the spread operator, and .0 is short for 0.0.
Spreading 0 (or any number) into an object yields an empty object, therefore {}.
Three dots in an object literal are a spread property, e.g.:
const a = { b: 1, c: 1 };
const d = { ...a, e: 1 }; // { b: 1, c: 1, e: 1 }
The last dot with a 0 is a number literal .0 is the same as 0.0. Therefore this:
{ ...(0.0) }
spreads all properties of the number object into the object, however as numbers don't have any (own) properties you get back an empty object.
In a simple terms {...} spread operator in javascript extends one object/array with another.
So, when babelifier tries extending one with another, it has to identify whether it is trying to extend an array or an object.
In the case of array, it iterates over elements.
In the case of object, it iterates over keys.
In this scenario, the babelyfier is trying to extract keys for number by checking the Object's own property call which is missing for number so it returns empty Object.
Spread operator {...} allows iterables to expand. It means that those data types that can be defined in form of key-value pairs can be expanded. In terms of Object we call key-value pair as Object property and it's value whereas in terms of arrays we can think index as key and element in array as it's value.
let obj = { a: 4, b: 1};
let obj2 = { ...obj, c: 2, d: 4}; // {a: 4, b: 1, c: 2, d: 4}
let arr1 = ['1', '2'];
let obj3 = { ...arr1, ...['3']}; // {0: "3", 1: "2"}
In terms of array, as it takes index as key so here it replaces element '1' of arr1 with '3' because both of them have same index in different array.
With strings too spread operator returns non-empty object. As string is an array of character so it treats string as an array.
let obj4 = {...'hi',...'hello'} // {0: "h", 1: "e", 2: "l", 3: "l", 4: "o"}
let obj5 = {...'y',...'x'} // {0: "x" }
But with other primitive data types it return empty object
with Numbers
let obj6 = { ...0.0, ...55} // {}
with Boolean
let obj7 = { ...true, ...false} // {}
In conclusion those data types that can be treated in form of key-value pairs when used with spread operator {...} returns non-empty object otherwise it returns empty object {}
When I run the following code:
var object1 = {
a: 1,
b: 2
};
var object2 = {
b: 4,
c: 3
};
var obj1Keys = Object.keys(object1);
var obj2Keys = Object.keys(object2);
console.log(obj2Keys[0] in obj1Keys);
The console logs false. Clearly both object1 and object2 have property 'b'. What am I doing wrong?
You need to use the includes() method instead.
console.log(obj1Keys.includes(obj2Keys[0]));
This is because the in operator works on object keys. The "keys" to an array are number indices (0, 1, etc), not their values
You need to take the object, not the array with the keys for checking and in operator. This check the keys of the object and arrays have indices and length property.
If you like to take the array with the keys, cou could use Array#includes.
var object1 = { a: 1, b: 2 },
object2 = { b: 4, c: 3 },
obj1Keys = Object.keys(object1),
obj2Keys = Object.keys(object2);
console.log(obj2Keys[0] in object1);
console.log(obj1Keys.includes(obj2Keys[0]));
By asking if obj2Keys[0] in obj1Keys, you're asking whether 'b' is a key of ['a', 'b']. It's not. It's a value of ['a', 'b']. You could check like this instead:
obj1Keys.includes(objKeys[0])
I have a json object that has encrypted values, I'll simplify this and pretend all values are numbers and i need the number x3 for this question. Is there a way to loop through the json object and update every value then return a decrypted version of the original object:
var encrypted = {
a: 10,
b: 4,
c: {x:3, y:2, z:1},
}
var decrypted = decryptJSON(encrypted) //<--- looking for this function
//decrypted = {
// a: 30,
// b: 12,
// c: {x:9, y:6, z:3},
// }
I've tried looping through the object using something like https://stackoverflow.com/a/29516227/620723 but this would only really work for a non nested json object.
Also the example I gave above is only nested one level in reality i may have nests inside nests inside nest inside....
You could write a recursive function to traverse the object and update your values. Here is a quick example:
var encrypted = {
a: 10,
b: 4,
c: {x: 3, y: 2, z: 1},
};
var updateObject = function (obj) {
for (var key in obj) {
obj[key] = updateValue(obj[key]);
}
return obj;
}
var updateValue = function(value) {
if (typeof(value) === "object") {
return updateObject(value);
} else {
return value * 3;
}
}
updateObject(encrypted);
console.log(encrypted);
Please note that this will only work as long as you only have objects and numeric values in your object. You will definitely need to adjust the functions if your data is more dynamic.
This should get you started though!