use nodejs var as json object statement? - node.js

how do I use a nodejs var inside a json statement, I dont realy have the required vocabulary to explain but here is my simplifyed code:
test.json:
{
"test1":["test1.1", "test1.2"],
"test2":["test2.1", "test2.2"]
}
test.js:
const json = require("./test.json")
function myFunction(TYPE){
return(json.TYPE[0])
}
console.log(myFunction("test1"))
as I use the "type" var it tries to uses it as an json statement or object but obviously there is no "type" there only is "test1" and "test2" but it interprets as "type" instead

Brackets to access the variable key should work
function myFunction(TYPE){
return(json[TYPE][0])
}

In JavaScript, json objects are pretty much same as plain JS objects. You need to use string as an index to access properties:
// This could be your json file, its almost the same
// Just require it like you did instead of using const JSON like i am
const json = {
"test1":["test1.1", "test1.2"],
"test2":["test2.1", "test2.2"]
}
function myFunction(TYPE){
// Access the json by using keyword directly as index string
return(json[TYPE])
// because TYPE is a string, TYPE[0] would mean first letter of TYPE string
}
function myFunctionDeeper(TYPE){
// To access a field and array in that field
return(json[TYPE][0])
}
console.log(myFunction("test1"))
console.log(myFunctionDeeper("test1"))
// example for what happens when accessing string by index
console.log("test1"[0])
Read more about objects here

Related

How to add TypeScript Interface to shorthand variable?

How to set TypeScript interface to variable looking like this:
const { body, statusCode } = await got.post('smth', requestOpts)
How can I set the interface to ex. body. I would like to assign there an interface with potential requests from the server. An interface that I'm willing to implement looks like that:
interface ResponseBody {
data: [{ username: string }]
}
I tried different things to attach this interface to the upper variable body but I'm getting build errors. The only workaround that I have here is to do not use shorthand variable but that's not my goal - I wonder if there are solutions for such issue.
TypeScript Playground
You'd need to annotate the whole object, like this:
const { body, statusCode }: { body: ResponseBody, statusCode: number } =
await got.post<ResponseBody>('users', requestOpts)
While it would be nice if you could annotate the individual destructured variables inside the object, this is not currently possible. The syntax const { body: ResponseBody } = ... can't work because JavaScript interprets this as assigning to a new variable name (so there'd be a variable named ResponseBody holding the value that was in the body property). Perhaps something like const { body::ResponseBody, statusCode::number } would work instead, as requested in microsoft/TypeScript#29526. But for now this is not possible, and you have to annotate the whole object.
That's the answer to the question as asked.
Do note that for your particular example, though, the got.post() method has a call signature that's generic in the type you expect the body property to be. So you can write
const { body, statusCode } = await got.post<ResponseBody>('users', requestOpts);
to get a strongly typed body variable with a minimum of extra keystrokes.
Playground link to code

SyntaxError: Unexpected token o in JSON at position 1 - Simple Error

I am currently taking a course on node.js and I am receiving this error:
SyntaxError: Unexpected token o in JSON at position 1
The code that I anticipate is giving me this problem is:
const loadNotes = function() {
// try {
//This code is exactly the same as the video's
const dataBuffer = fs.readFileSync('notes.json')
const dataJSON = JSON.toString(dataBuffer)
return JSON.parse(dataJSON)
//} catch(e) {
//return []
// }
I checked similar answers, but they seemed more complex, and as such, I was unable to fix the problem using them.
Your JSON.toString() is not returning what you think it is.
toString() is returning a string representation of the JSON object.
The result is: [object JSON]
That is not a proper JSON string so JSON.parse() fails.
So, there are two problems:
You are incorrectly using the prototype toString() method
You are feeding a non-JSON string to JSON.parse()
Explanation:
Firstly, as was stated in the comments above, there is no toString() method defined in the JSON object. .toString() in the JSON object's prototype chain does do something when you call it but the result is a string representation of the JavaScript JSON object, not the JSON object you are attempting to read from your file. You really want to use JSON.stringify() instead of toString().
Here's the explanation in MDN:
Every object has a toString() method that is automatically called when
the object is to be represented as a text value or when an object is
referred to in a manner in which a string is expected. By default, the
toString() method is inherited by every object descended from Object.
If this method is not overridden in a custom object, toString()
returns "[object type]", where type is the object type.
So, you can call toString() on any object in JavaScript and get [object Object]. But that's not what you want. So, don't use toString(). It's not doing what you think it's doing.
Secondly, be sure that you are trying to parse a real JSON string and not trying to parse a JavaScript object. There is a significant difference between the two.
Take a look at this code:
let dataJS = {
key: "value"
}
Above, I have defined a JavaScript object called dataJS.
I can convert the dataJS JavaScript object into a JSON object by using the JSON.stringify() method like this:
let dataJSON = JSON.stringify(dataJS);
The JSON.stringify() method expects a JavaScript object and will return a JSON string. I have assigned the resulting JSON string to dataJSON. Now, I have two things: a JavaScript object called dataJS and a JSON string called dataJSON.
I can print the contents of these two things like this:
console.log("JSON:\n", dataJSON)
console.log("JS:\n", dataJS)
Notice carefully how the two appear. You'll see this:
JSON:
{"key":"value"}
JS:
{ key: 'value' }
Do you see the difference in between the JSON string and the JavaScript object?
The JSON string has double-quotes around the key and values. The JavaScript object does not have any quotes around the key and single-quotes around the value.
These make JSON strings and JavaScript objects quite different.
So, if you accidentally feed the wrong thing to the JSON.parse() method you will get an error. Note what happens when I give the JSON object to the JSON.parse() method:
console.log("Parse JSON:\n", JSON.parse(dataJSON))
/* result will be:
* Parse JSON:
* { key: 'value' }
*/
That is great! The JSON.parse() method is expecting a JSON string so it works properly.
But watch what happens then I try to feed JSON.parse() the JavaScript object we created:
console.log("Parse JS:\n", JSON.parse(dataJS))
/* result will be an ERROR:
* undefined:1
* [object Object]
* ^
*
* SyntaxError: Unexpected token o in JSON at position 1
*/
There's your error!
So, it means that what you're feeding your JSON.parse() method in your code is not a JSON string.
The "Unexpected token" error means that your JSON isn't formatted correctly. You can take a look at this site and put the contents of notes.json into it, and it will tell you whats wrong and what needs to be corrected

Error: Argument "data" is not a valid Document. Input is not a plain JavaScript object

I am getting the error
Error: Argument "data" is not a valid Document. Input is not a plain
JavaScript object.
when updating a document, using firebase admin SDK. Here the Typescript code.
var myDoc = new MyDoc();
myDoc.Public.Name = "Jonh Doe" //setup up content
admin.firestore()
.collection('MyDocs')
.doc("Id1")
.set(myDoc);
I did something similar:
var myDoc = <MyDoc> {
Public: {
Name: "Jonh Doe"
}
}
It is semantically the same, I just think it is a bit cleaner.
In case some else bump into the same issue, the solution is to simple use Json to instantiate the object, like this:
var myDoc = {
Public: {
Name: "Jonh Doe"
}
} as MyDoc; //keep type to still get typescript compiler validations
I had same problem, in my case I'd forgot to add Content-Type:application/json to my header when sending request, and then the object was treated as string and I got that error.
You can recreate js object via; {...__data}
return refDB.set({...__data}).then((newData) => {
})

Calling function with callback defined as string

var method = 'serviceName.MethodName'
I Just want to call it like
serviceName.methodName(function(output callback){
});
Is there any approach to call it.thanks
There are two methods that I can think of now.
JS eval
You can use the javascript eval function to convert any string into code snippet like below. Although eval is a quick solution but should not be used unless you dont have any other option by your side.
var method = 'UserService.getData';
eval(method)();
Factory pattern
Use a below pattern to get the service
You would need to define the services in such a manner that you can access them using a pattern.
var Services = {
// UserService and AccountsService are again objects having some callable functions.
UserService : {getData: function(){}, getAge: function(){}},
AccountsService : {getData: function(){}, getAge: function(){}},
// getService is the heart of the code which will get you the required service depending on the string paramter you pass.
getService : function(serviceName){
var service = '';
switch(serviceName){
case 'User':
service = this.UserService;
break;
case 'Accounts':
service = this.AccountsService;
break;
}
return service;
}
}
You can use get the required service with below code
Services.getService('User')
I'm not aware of any way you can resolve the serviceName part of that string to an object, without using eval. So obviously you need to be extremely careful.
Perhaps:
if (method.match(/^[a-zA-Z0-9_]+\.[a-zA-Z0-9_]+$/) {
var servicePart = eval(method.split('.')[0]);
var methodPart = method.split('.')[1];
servicePart[methodPart](...)
}
There are two separate problems in your question:
How to access object property by property name (string)?
How to access object by it's name (string)?
Regarding the first problem - it is easy to access object property by string using the following notation:
const myObject = {
myProp: 1,
};
console.log(myObject['myProp']);
And regarding the second problem - it depends on what serviceName is:
if it is a property of some other object, then use someObject['serviceName']['MethodName']
if it is a local variable, consider using a Map (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) to associate strings with objects;

Jade/Pug - appending to a class name

Hello I have a unique id in an object and I want to append it to a class name. I am trying to do something like the following but it isn't working:
myJadeFile:
.googleChartContainer-#{attendanceAnalytics.uid}
myRoute.js:
res.render('./edu/school_dashboard_elementary', { attendanceAnalytics:attendanceChart });
I suppose I could create a class name in my route and send it as a variable with something like:
var className = '.googleChartContainer-attendanceChart.uid}';
res.render('./edu/school_dashboard_elementary', { attendanceAnalytics:attendanceChart, attendanceClassName:className });
and then in the jade file:
#{attendanceClassName} //- output is .googleChartContainer-someUid?
I was wondering if there was a way to get the first approach to work correctly, or if there is another preferred way.
Thanks!
You have two choices. You can do it the JavaScript way with a string, like:
div(id=attendanceAnalytics.uid, class='googleChartContainer-' + attendanceAnalytics.uid)
or you create an JavaScript object containing keys and values to use them with the typical jade attribute div&attribute(object), like this:
- var attr = {"id": attendanceAnalytics.uid, "class": 'googleChartContainer-' + attendanceAnalytics.uid}
div&attribute(attr)
Take a look into the JadeLang Docs, chapter attributes.

Resources