Reading from JSON returns undefined - javascript

I'm trying to read from a JSON that contains my error messages, so that in case I'd ever want to change what my error messages say, I'd just change the JSON instead of diving into my source code. Everything seems to be working fine...
var fs = require('fs')
console.log("Now reading from error messages configuration file...");
var errorMsgs = JSON.parse(fs.readFileSync('config/error_msgs.JSON'));
console.log(errorMsgs)
This is what's in errorMsgs.json:
{
"bad_password" : [
{
"error" : "Incorrect login credentials.",
"details" : "This happens if you either have an incorrect username or password. Please try again with different credentials."
}
],
"missing_fields" : [
{
"error" : "Credentials failed to parse.",
"details" : "This happens when one or more fields are missing (or have illegal characters in them), please try again with different credentials."
}
]
}
When I log to the console, errorMsgs displays fine. When I log one of the items that errorMsgs has (like bad_password), it also works fine, as in it displays the items that are nested inside. However, when I attempt to retrieve a specific value like errorMsgs.bad_password['error'], it returns undefined. I can't seem to figure it out. I tried dot notation (errorMsgs.bad_password.error), which returns undefined. I tried the method above (errorMsgs.bad_password['error']) which also returns undefined. Asking for the typeof of errorMsgs, it returns object, which I assume makes it not a string. Passing the value to a variable first and then logging the variable doesn't do anything either. Is node converting it to a string on-the-fly, causing it to return undefined, or am I just doing something wrong?

bad_password" : [
{
"error" : "Incorrect login credentials.",
"details" : "This happens if you either have an incorrect username or password. Please try again with different credentials."
}
],
Your nested object is contained in an array.
errorMsgs.bad_password[0]['error']
This is what you're looking for. Just grab the first value of the array

Related

Can only access some javascript object keys

I am noticing strange behavior from a javascript object in my Node application. The user object is created by parsing a csv file with two columns: Email and ID. For some reason, I can only access one of the fields using the typical methods. The other field always returns undefined. I am using Node 15.12.0.
When I log the user object, it returns: { 'Email': 'email#example.com', ID: '12345' }
Curiously, the ID field does not have quotes when it is logged, but the Email field does have quotes.
I can access user.ID as usual, but user.Email returns undefined.
console.log(Object.keys(user)); // [ 'Email', 'ID' ]
console.log(user.ID); // 12345
console.log(user.Email); // undefined
console.log(user['Email']) // undefined
console.log(user["Email"]) // undefined
console.log(user.email) // undefined
console.log(user["\'Email\'"]) // undefined
console.log(user["'Email'"]) // undefined
console.log(user[Object.keys(user)[0]]) // email#example.com
console.log(Object.values(user)[0]) // email#example.com
I have tried the using JSON.parse(JSON.stringify(user)), but I get the same results as before.
The only way I can access the Email field is by using the user[Object.keys(user)[0]] or Object.values(user)[0] which is very strange to me.
I would appreciate any ideas you have to figure out whats happening here. Is there something I can do to examine the object more closely? Does the quotes around the keys indicate anything?

Getting the values from a JSON into a discord.js embed

I'm making a discord.js bot where all the command data is stored in a JSON file and when the help command is run, I want it to iterate through the JSON, at the level the user entered.
So far, I've managed to check if the value entered is a command or a category, and I have been able to console.log all the information and it shows the correct data I want to display on the embed.
For example, in my JSON file I have:
{
"category1": {
"command1": {
"Aliases": [],
"Description": "Runs a command"
}
}
}
When I do the console.log() when the user runs g!help category1 it outputs:
command1
Runs a command
and when it sends the embed I get:
[object Object]
undefined
Here is the part of the code which iterates through the JSON and adds the data to the embed:
for (ctg in help_data) {
if (args[0] === ctg) {
embed.setTitle(ctg)
for (command in help_data[ctg]) {
var cmd = command
var desc = help_data[ctg][command].Description
console.log(cmd)
console.log(desc)
embed.addField({
"name": cmd,
"Value": desc
})
}
}
}
I don't understand why it changes between the console.log and the embed.addField, if someone could please explain why this happens and how I can fix it, that would be amazing!
embed.addField takes three parameters, the first is the name of the field, the second is its value. Both of these are strings. In your example, your first argument is an object that gets converted to a string (and hence becomes [object Object]) and the second one (as you don't provide anything) is undefined.
To fix this, you can either add the two strings like this:
embed.addField(cmd, desc);
Or use the addFields method instead, that accepts an object like this:
embed.addFields({
name: cmd,
value: desc,
});

Getting an error with Twitter lib

In Google Apps Script I have this snippet of code in my project to send a tweet (also in jsBin):
function sendTweet(status) {
var twitterKeys= {
TWITTER_CONSUMER_KEY: "x",
TWITTER_CONSUMER_SECRET: "x",
TWITTER_ACCESS_TOKEN: "x",
TWITTER_ACCESS_SECRET: "x"
};
var props = PropertiesService.getScriptProperties();
props.setProperties(twitterKeys);
twit = new Twitter.OAuth(props);
var service = new Twitter.OAuth(props);
if ( service.hasAccess() ) {
var response = twit.sendTweet(status);
if (response) {
Logger.log("Tweet ID " + response.id_str);
} else {
// Tweet could not be sent
// Go to View -> Logs to see the error message
}
}
}
sendTweet("test");
But the problem I'm having is that I get this error:
TypeError: Cannot read property "text" from undefined. (line 293, file "twitter", project "Twitter lib")
Line 293 is from version 21 of the "Twitter lib" library (MKvHYYdYA4G5JJHj7hxIcoh8V4oX7X1M_).
The message "test" actually gets tweeted, despite that error. Does anyone know how to fix it?
Hi, author of Twitter Lib here. #Mogsdad pointed me here over Twitter. I think I know what's going on with your script, and it's a peculiarity of how Google Script works.
You have most of your code in a function that takes an argument, and then you have a call to the function at the top level of your script. What happens, when you go to the "Run" menu and select your sendTweet function, is that the script at the top level gets run before the selected function is executed, and the tweet would be sent at that time with the "test" text.
Then after that, sendTweet gets run with no arguments, meaning the status variable is undefined. You're sending an undefined value into twit.sendTweet(), causing the error you see.
What I'd recommend here is simply wrapping your last line of code into a function so you can call it from the Run menu, like this:
function sendTestTweet() {
sendTweet("test");
}
Just to recap, the error you've seen is:
TypeError: Cannot read property "text" from undefined. (line 293, file "twitter", project "Twitter lib")
That is in the sendTweet() method of the library, see below.
/**
* Upload a tweet to Twitter with optional media.
*
* #param {string | Tweet} tweet the status text to send as a Twitter update
* #param {optional object} params any additional parameters to send as part of the update post
* #return {object} the Twitter response as an object if successful, null otherwise
*/
OAuth.prototype.sendTweet = function(tweet, params) {
var i;
var payload = { //<=== 293
"status" : (tweet.text || tweet)
};
Your code invokes this method with a single string parameter, status, which is set to "test".
The author of the library allowed for the tweet parameter to be one of two things:
It can be an object with a text property containing the message to Tweet, or
It can be a string.
However, the way that's being handled checks for tweet.text first, then if that does not exist it checks for a string tweet. When tweet.text does not exist (i.e. when using just a string), that TypeError is thrown.
I've reached out to the library author so they can publish the fix. However, in the meantime you can send a Tweet object with a text property, or take a copy of the library and update it yourself.
Send Tweet object. The Tweet object is documented in the Twitter API v1.1 documentation, but since the only property involved in this operation is text, a simple change in your status function will do the trick. Just ensure that status is an object with a text property.
function sendTweet(status) {
if (typeof status === string)
status = {text:status};
...
Update the library yourself.
To avoid the error, and handle the parameter options properly, line 294 in the library should be:
"status" : (tweet.hasOwnProperty("text") ? tweet.text : tweet)
Or:
"status" : (typeof tweet === 'object' ? tweet.text : tweet)
You'll need to publish it, and update the library ID in your code, but that should take care of this problem. Once a library update is available, you can switch back.

Avoid 'Cannot read property of undefined' error when mapping data

I'm receiving some data back from Google Books API calls and I'm mapping the data into a lighter array I can then work with. I'm using this line to map the data I'm interested into:
data.items.map(function(book) {
return { googleId : book.id, image : book.volumeInfo.imageLinks.thumbnail, authors : reduceAuthors(book.volumeInfo.authors), title : book.volumeInfo.title, subtitle : book.volumeInfo.subtitle, publishedDate : book.volumeInfo.publishedDate, publisher : book.volumeInfo.publisher}
});
Most of the times it works just fine, but some times one of the elements is missing, may it be imagelinks or authors therefore I get this error "Uncaught TypeError: Cannot read property of undefined".
What is the best way to avoid this error?
The only solution I have in mind is to first run a sanity check on the whole data and apply the map only after, but there maybe is a better solution? And wrapping everything in a try and catch throws me out of the mapping operation too early and doesn't complete with the rest of the data.
You can check it inside map() function, without handle previously the entire data. With a ternary conditional , something like this:
image : ((book.volumeInfo.imageLinks) ? book.volumeInfo.imageLinks.thumbnail : undefined)
So if book.volumeInfo.imageLinks is null/empty/undefined there aren't error and the value inserted will be undefined, otherwise catch the thumbnail value.

JavaScript JSON Parse Issue ($.getJSON)

I can't seem to get the following code to output anything to the screen. JavaScript is not my strong suit!
This is the JavaScript code calling a local file that outputs a list of rooms
$.getJSON('roomupdate.php?level=1&div=1&callback=json',function(res){
console.log(res.rooms.name[0]);
});
In the above I'm merely trying to see the name of the first room in the console. And this is the JSON output (Which I can confirm the script can see and load)
json(
{
"rooms":
[
{ "name" : "Bedroom" },
{ "name" : "Living Room" },
{ "name" : "Lounge" },
{ "name" : "Kitchen" }
]
})
Could anyone suggest what I am doing wrong? Even to view in the console?
Lastly, can you loop through the array?
Your JSON data contains an object rooms and this object actually contains an array [], So to access the data inside your array you need to put the index on rooms :
console.log(res.rooms[0].name);
Use callback=? rather than callback=json so that jQuery knows you are using JSONp and can choose it's own name for the callback function.
$.getJSON('roomupdate.php?level=1&div=1&callback=?',function(res){
//alert('Your name is '+res.rooms);
console.log(res.rooms.name[0]);
});
See http://api.jquery.com/jQuery.getJSON/#jsonp for details.
Edit:
Looking again, you will need to change the way you are accessing the data around. res.rooms.name[0] should be res.rooms[0].name because rooms is a list, and each room has a name property.
This will loop through the array of rooms and log the name of each one:
$.each( res.rooms, function( i, room ) {
console.log( room.name );
});
If that doesn't work, then add this statement at the beginning of your callback (where you have the console.log() call now):
debugger;
Load/run your page with the developer tools open, and it will stop in the debugger where you have that statement. Now you can look at all your variables in detail, try out expressions to see what they do, single step through your code, etc.

Categories

Resources