`require()` converts the string literal "true" to the boolean true - node.js

I have the following mapping in a JSON file:
"mapping": [
{
"true": "some string"
},
{
"false": "some other string"
}
]
In such a mapping, the keys are always strings. That's why I need the keys to be strings, even though, in this case, they are string representations of the boolean values.
When I load this JSON file with require(myfile.json), the keys are somehow converted to actual boolean values.
Is that a bug in require()? Is there a workaround?

That is not a require thing. Javascript allows to use any item as object keys, but then under the hood calls toString when saving or retrieving the item. For instance:
const a = {};
a[true] = 'value from true';
a[{somekey: 'somevalue'}] = 'value from object';
Object.getKeys(a); // ["true", "[object Object]"]
So your problem is related to the way javascript handles object keys. There is no way to discriminate between true and 'true' when storing a value in an object key:
a = {};
a[true] = 'from plain true';
a["true"] = 'from stringified true';
a[true]; // "from stringified true". See how the second assignation messes with the first, even if we are using the boolean true value as key.
For reference: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_Objects

Related

Terraform test for null or false value of object key

Hopefully a relatively straightforward one. I have an object that uses the experimental optional attrs feature.
This means that one of the object attributes/keys do not need to be present. I then need to test for either null or false value of said object key in object composition with for loop.
When using the module_variable_optional_attrs experiment, it seems that if you use lookup() to find an object key which does not exist it'll always return null, not the default, as you might expect it to.
I now am having to test with a conditional (lookup(connection, "auto_accept", false) == false || lookup(connection, "auto_accept", false) == null)
this doesn't seem very clean. looking for suggestions on improvements.
EDIT
main.tf
terraform {
# Optional attributes and the defaults function are
# both experimental, so we must opt in to the experiment.
experiments = [module_variable_optional_attrs]
}
variable "example_var" {
type = list(object({
name = string
auto_accept = optional(bool)
}))
description = "Some variable"
default = [{
name = "example-name"
}]
}
Below commands are run from terraform console
> lookup(var.example_var[0], "auto_accept")
false
# now lets make the key undefined
> lookup(var.example_var[0], "auto_accept")
tobool(null)
> lookup(var.example_var[0], "auto_accept", false)
tobool(null)
> tobool(null)
null
I have been in a similar scenario where I had following input map:
payload = {
name = "SomeTestName"
optional_attr = "SomeOptionalAttribue"
}
The above payload could have following possible inputs:
payload = {
name = "SomeTestName"
optional_attr = "SomeOptionalAttribue"
}
OR
payload = {
name = "SomeTestName"
}
OR
payload = {
name = "SomeTestName"
optional_attr = null
}
My use case is to look for optional_attr in the payload and take its value as key and get corresponding value from the following map. If optional_attr is null or not provided then I take default value of mydefault key from the following map:
master_data = {
optional_attr_value1 = "value1"
optional_attr_value2 = "value2"
mydefault = "default_value"
}
Following combination of lookup with null check worked for me:
value = lookup(master_data, can(coalesce(payload.optional_attr)) ? lookup(tomap(payload), "optional_attr", "mydefault") : "mydefault" , "default_value")
What above code does is first it checks if optional_attr is not provided at all in the payload or its provided with a value of null. If this is true then the ternary statement returns false and "mydefault" value is provided that is used by outside lookup function to get mydefault key's corresponding value from master_data. If ternary operator returns true (optional_attry is provided with a value) then the internal lookup function is triggered and it will return value from master_data corresponding to whatever key provided as a value of optional_attr. Again if optional_attr value does not match any key in the master_data then default key of my_default is returned by internal lookup function.

How do I access content from JSON string?

I am receiving a JSON object from the backend now I just want "result" array only in my template variable in my angular application from it.
{
"result":[
{"name":"Sunil Sahu",
"mobile":"1234567890",
"email":"abc#gmail.com",
"location":"Mumbai",
"Age":"19"
}
],
"status":200
}
Try with
variable_name["result"].
Try with
var data = response from the backend
var result = data.result;
$var = '{"result":[{"name":"Sunil Sahu","mobile":"1234567890","email":"abc#gmail.com","location":"Mumbai","Age":"19"}],"stats":200}';
If your $var is string, you need to turn it to "array" or "object" by json_decode() function
object:
$var_object = json_decode($var); //this will get an object
$result = $var_object->result; //$result is what you want to get
array:
$var_array = json_decode($var, true); //this will get an array
$result = $var_array['result']; //$result is what you want to get
Else if $var is object, direct use
$result = $var->result; //$result is what you want to get
As result is an array of objects, you can either use any loop to extract key value pair or you can directly access the array using index value.
var results = data["result"] // this would return an array
angular.forEach(results, function(value, key) {
//access key value pair
});
For accessing results in HTML, ng-repeat directive can be used.
Your question didn't explain further, but in the simple way try this :
const stringJson = `{
"result":[
{"name":"Sunil Sahu",
"mobile":"1234567890",
"email":"abc#gmail.com",
"location":"Mumbai",
"Age":"19"
}
],
"status":200
}`
const obJson = JSON.parse(stringJson);
console.log(obJson.result);

How do I filter keys from JSON in Node.js?

I'm trying to select certain keys from an JSON array, and filter the rest.
var json = JSON.stringify(body);
which is:
{
"FirstName":"foo",
"typeform_form_submits":{
"foo":true,
"bar":true,
"baz":true
},
"more keys": "foo",
"unwanted key": "foo"
}
Want I want:
{
"FirstName":"foo",
"typeform_form_submits":{
"foo":true,
"bar":true,
"baz":true
}
}
I've checked out How to filter JSON data in node.js?, but I'm looking to do this without any packages.
Now you can use Object.fromEntries like so:
Object.fromEntries(Object.entries(raw).filter(([key]) => wantedKeys.includes(key)))
You need to filter your obj before passing it to json stringify:
const rawJson = {
"FirstName":"foo",
"typeform_form_submits":{
"foo":true,
"bar":true,
"baz":true
},
"more keys": "foo",
"unwanted key": "foo"
};
// This array will serve as a whitelist to select keys you want to keep in rawJson
const filterArray = [
"FirstName",
"typeform_form_submits",
];
// this function filters source keys (one level deep) according to whitelist
function filterObj(source, whiteList) {
const res = {};
// iterate over each keys of source
Object.keys(source).forEach((key) => {
// if whiteList contains the current key, add this key to res
if (whiteList.indexOf(key) !== -1) {
res[key] = source[key];
}
});
return res;
}
// outputs the desired result
console.log(JSON.stringify(filterObj(rawJson, filterArray)));
var raw = {
"FirstName":"foo",
"typeform_form_submits":{
"foo":true,
"bar":true,
"baz":true
},
"more keys": "foo",
"unwanted key": "foo"
}
var wantedKeys =["FirstName","typeform_form_submits" ]
var opObj = {}
Object.keys(raw).forEach( key => {
if(wantedKeys.includes(key)){
opObj[key] = raw[key]
}
})
console.log(JSON.stringify(opObj))
I know this question was asked aways back, but I wanted to just toss out there, since nobody else did:
If you're bound and determined to do this with stringify, one of its less-well-known capabilities involves replacer, it's second parameter. For example:
// Creating a demo data set
let dataToReduce = {a:1, b:2, c:3, d:4, e:5};
console.log('Demo data:', dataToReduce);
// Providing an array to reduce the results down to only those specified.
let reducedData = JSON.stringify(dataToReduce, ['a','c','e']);
console.log('Using [reducer] as an array of IDs:', reducedData);
// Running a function against the key/value pairs to reduce the results down to those desired.
let processedData = JSON.stringify(dataToReduce, (key, value) => (value%2 === 0) ? undefined: value);
console.log('Using [reducer] as an operation on the values:', processedData);
// And, of course, restoring them back to their original object format:
console.log('Restoration of the results:', '\nreducedData:', JSON.parse(reducedData), '\nprocessedData:', JSON.parse(processedData));
In the above code snippet, the key value pairs are filtered using stringify exclusively:
In the first case, by providing an array of strings, representing the keys you wish to preserve (as you were requesting)
In the second, by running a function against the values, and dynamically determining those to keep (which you didn't request, but is part of the same property, and may help someone else)
In the third, their respective conversions back to JSON (using .parse()).
Now, I want to stress that I'm not advocating this as the appropriate method to reduce an object (though it will make a clean SHALLOW copy of said object, and is actually surprisingly performant), if only from an obscurity/readability standpoint, but it IS a totally-effective (and mainstream; that is: it's built into the language, not a hack) option/tool to add to the arsenal.

Node-red:node-function - missing "null" value in if condition

I'm using Node-Red and in node function I have:
...
res = dataTransform.transform();
//critic case: res = [{"pressure":null}];
key = Object.keys(res[0]);
if(res[0][[key]]!=null)
{
...
console.log("res: ", [key]+":"+res[0][[key]]);
}
on console.log I have always:
res: 0:[object Object]
And it enters in if-statement always (also when the "res[0][[key]]" is null).
What was I mistake?
Object.keys returns an array containing the keys of the Object. Your code is using that entire array rather than a value from within it.
In order to get to the value of pressure, you would use:
var keys = Object.keys(res[0]);
var key = keys[0];
if (res[0][key] != null) {
console.log(res[0][key]);
}

How to use dot(.) to MongoDB(Mongoose) schema as a parameter [duplicate]

It's difficult to explain the case by words, let me give an example:
var myObj = {
'name': 'Umut',
'age' : 34
};
var prop = 'name';
var value = 'Onur';
myObj[name] = value; // This does not work
eval('myObj.' + name) = value; //Bad coding ;)
How can I set a variable property with variable value in a JavaScript object?
myObj[prop] = value;
That should work. You mixed up the name of the variable and its value. But indexing an object with strings to get at its properties works fine in JavaScript.
myObj.name=value
or
myObj['name']=value (Quotes are required)
Both of these are interchangeable.
Edit: I'm guessing you meant myObj[prop] = value, instead of myObj[name] = value. Second syntax works fine: http://jsfiddle.net/waitinforatrain/dNjvb/1/
You can get the property the same way as you set it.
foo = {
bar: "value"
}
You set the value
foo["bar"] = "baz";
To get the value
foo["bar"]
will return "baz".
You could also create something that would be similar to a value object (vo);
SomeModelClassNameVO.js;
function SomeModelClassNameVO(name,id) {
this.name = name;
this.id = id;
}
Than you can just do;
var someModelClassNameVO = new someModelClassNameVO('name',1);
console.log(someModelClassNameVO.name);
simple as this
myObj.name = value;
When you create an object myObj as you have, think of it more like a dictionary. In this case, it has two keys, name, and age.
You can access these dictionaries in two ways:
Like an array (e.g. myObj[name]); or
Like a property (e.g. myObj.name); do note that some properties are reserved, so the first method is preferred.
You should be able to access it as a property without any problems. However, to access it as an array, you'll need to treat the key like a string.
myObj["name"]
Otherwise, javascript will assume that name is a variable, and since you haven't created a variable called name, it won't be able to access the key you're expecting.
You could do the following:
var currentObj = {
name: 'Umut',
age : 34
};
var newValues = {
name: 'Onur',
}
Option 1:
currentObj = Object.assign(currentObj, newValues);
Option 2:
currentObj = {...currentObj, ...newValues};
Option 3:
Object.keys(newValues).forEach(key => {
currentObj[key] = newValues[key];
});

Resources