Can't access property in returned object - javascript

I've got a problem where I can't seem to query my JSON coming back, I can print out the entire response though, here's my JSON response, I can only see this when I do a msgBox() prompt:
{ "Addresses" :
"[{
Building=Megatron Skyscraper,
BuldingId=1998,
AccountId=2000,
Number=007,
Name=Megatron
},{
Building=StarScream Skyscraper,
BuldingId=1999,
AccountId=2001,
Number=008,
Name=StarScream
}]"}
And here's my code:
function getReadyStateHandler(req)
{
// Return an anonymous function that listens to the
// XMLHttpRequest instance
return function ()
{
// If the request's status is "complete"
if (req.readyState == 4)
{
// Check that a successful server response was received
if (req.status == 200)
{
msgBox("JSON Response recieved...");
var addresses = req.responseText.toJSON();
msgBox(req.responseText.toJSON());
}
else
{
// An HTTP problem has occurred
alert("HTTP error: " + req.status);
}
}
}
}
I've tried everything from addresses.Address[0].City and addressess.Addresses[0].City and many others - but this is slightly confusing!

Apart from the fact that there's no City key in your response, your returned object contains only one (malformed) string, not an array of objects. You can check this using http://jsonlint.com
How did you create the response? It should look more like:
{ "Addresses" : [{
"Building":"Megatron Skyscraper",
"BuldingId":1998,
"AccountId":2000,
"Number":7,
"Name":"Megatron"
},{
"Building":"StarScream Skyscraper",
"BuldingId":1999,
"AccountId":2001,
"Number":8,
"Name":"StarScream"
}]}
Update: those leading zeros in "Number":007 and "Number":008 may cause problems, because they will be interpreted as octal values. I've removed them in my answer.

Your response is valid but Addresses is a string and not an array. The quotes shouldn't be there if it is to be treated like an array. You could hack it a bit if you wanted and do
address = JSON.parse(addresses.Addresses);

Related

Using Lambda with Nodejs Count Some queries in Dynamo DB

After using the below to pull data from Dynamo db sucessfully
async function pullone(sessionid) {
const params = {
TableName: dynamodbTableName,
Key: {
'sessionid': sessionid
}
};
return await dynamodb.get(params).promise().then((response) => {
return response.Item
}, (error) => {
console.error('Do your custom error handling here. I am just gonna log it: ', error);
});
}
Instead of 'return response.Item' i just want to return the count instead.
I tried doing count(pullone(sessionid)) but not sure if that is even a valid method. Please assist
Not sure if I understood your question, but:
Since you're requesting data associated with a primary key, you'll get either 0 or 1 element in Item.
So, if you aim to know if "you've found something or not", you can use Number(response.Item != null) and you'll get 1 in case of "something" and 0 in case of "nothing".
If, instead, your data contains a "count" attribute, then (await pullone(sessionId)).count should work.
Otherwise, you have to query your DB (but you'll get Items (plural) in your response) and use the length() function of the Items array you'll get in the response.

JS/NodeJS/VSCode - How to step into a console logged object [duplicate]

In the below code (running on Node JS) I am trying to print an object obtained from an external API using JSON.stringify which results in an error:
TypeError: Converting circular structure to JSON
I have looked at the questions on this topic, but none could help. Could some one please suggest:
a) How I could obtain country value from the res object ?
b) How I could print the entire object itself ?
http.get('http://ip-api.com/json', (res) => {
console.log(`Got response: ${res.statusCode}`);
console.log(res.country) // *** Results in Undefined
console.log(JSON.stringify(res)); // *** Resulting in a TypeError: Converting circular structure to JSON
res.resume();
}).on('error', (e) => {
console.log(`Got error: ${e.message}`);
});
Basic console.log will not go through long and complex object, and may decide to just print [Object] instead.
A good way to prevent that in node.js is to use util.inspect:
'use strict';
const util = require('util'),
obj = /*Long and complex object*/;
console.log(util.inspect(obj, {depth: null}));
//depth: null tell util.inspect to open everything until it get to a circular reference, the result can be quite long however.
EDIT: In a pinch (in the REPL for example), a second option is JSON.stringify. No need to require it, but it will break on circular reference instead of printing the fact there is a reference.
Print the whole object, it will not have problems with recursive refferences:
console.log(res);
Here's an example for you to see how console.log handles circular refferences:
> var q = {a:0, b:0}
> q.b = q
> console.log(q)
{ a: 0, b: [Circular] }
Also, I would advise to check what data are you actually receiving.
By using the http request client, I am able to print the JSON object as well as print the country value. Below is my updated code.
var request = require('request');
request('http://ip-api.com/json', function (error, response, body) {
if (!error && response.statusCode == 200) {
console.log(response.body); // Prints the JSON object
var object = JSON.parse(body);
console.log(object['country']) // Prints the country value from the JSON object
}
});
This can print the key of the object and the value of the object in the simplest way. Just try it.
const jsonObj = {
a: 'somestring',
b: 42,
c: false
};
Array.from(Object.keys(jsonObj)).forEach(function(key){
console.log(key + ":" + jsonObj[key]);
});
In 2021, I just printed using
app.post("/",(req,res) => {
console.log("HI "+JSON.stringify(req.body));
res.send("Hi")
});
and got my output as HI {"Hi":"Hi"}.
I sent
{
"Hi": "Hi"
}
as my post request body.
Only doing console.log(req.body) printed [object Object] on console but now this works.
Use console.dir and set the depth.
console.dir(obj, { depth:10 })
Alternatively you can set the default depth to change the console.log depth.
require('util').inspect.defaultOptions.depth = 10
All of this and details about this can be found in nodejs training.
https://nodejs.dev/learn/how-to-log-an-object-in-nodejs
You do not actually get data in res. You need on('data') and on.('end')
body is a string. It gets append on data received, so on complete you will need to parse data into json
http.get("http://ip-api.com/json", function(res) {
var body = '';
res.on('data', function(data){
body = body + data;
});
res.on('end', function() {
var parsed = {};
try{
parsed = JSON.parse(body); // i have checked its working correctly
}
catch(er){
//do nothing it is already json
}
console.log(parsed.country);
});
});
Noe from parsed which is a json object, you can get any property
You can pass two arguments to console.log()
Try this code after installing "yargs" And it will print whole object
console.log('object is' , yargs.argv);
I think may be it will help you to print whole object :)

CouchDB update handlers: document id must not be empty

I wrote simple update handler:
{
"handler": "function (doc, req) { if (req.userCtx.roles.indexOf('editor') < 0) return [req.userCtx, 'access error']; if (!doc) { return [doc, 'nothing']; } doc.date = new Date(); doc.edited_by = req.userCtx.name; return [doc, toJSON(doc)]; }"
}
When I'm trying to query from Mozilla HttpRequester http://192.168.0.34:5984/records/_design/records/_update/handler, i'm getting
with that's data
{"title":"testtest","content":"test"}
And getting
{"error":"bad_request","reason":"Document id must not be empty"}
I've added _id to JSON
{"_id":"testid","title":"testtest","content":"test"}
No luck.
Update: and running that query in browser returns nothing, which may indicate that there's no document sent, but that's not true. What i'm doing wrong?
In CouchDB update handler _id never been set automatically, so you must do it manually. The simplest solution is using uuids, which available at req.uuid.
One important thing about update handlers. Their syntax someplace strange: you can't take data and return doc, no. Your update handler taking doc and req objects, where first is a changing document (check document existence using !doc, if it returns true — you can create new) and the second is request data, including access info, uuid and body. We're getting data from server not in req, but in req.body, which is raw string. Is must be parsed first using JSON.parse(req.body). After doing some checks, we can return — but return also not easy. If we have a doc — we're changing it, if not — we're creating new object. Return must be done by array [data_to_be_written, return_data], where first item is document for database and the second is a string (and only string, use toJSON(object) to return objects).
In addition there's my update handler function example, there's a lot of dirty debug code and it can be wrong, but it working on creation (update still unchecked).
function (doc, req) {
if (req['userCtx']['roles'].indexOf('editor') < 0) {
return [null, 'Access denied'];
}
var rcv = JSON.parse(req.body);
if (!doc) {
if (!rcv['_id'] && !!rcv['title'] && !!rcv['content']) {
return [{ '_id':req.uuid,'title': rcv['title'], 'content': rcv['content'], 'date': new Date(), 'edited_by': req['userCtx']['name'] }, 'Created' + toJSON(req)];
}
return [null, 'Empty' + toJSON({ 'no_id': !rcv['_id'], 'title': !!rcv['title'], 'content': !!rcv['content'], 'body':req.body })];
}
doc['date'] = new Date();
doc['edited_by'] = req['userCtx']['name'];
return [doc, 'Edited' + toJSON(doc)];
}
P.S> and remember, that even update handler working over validation func, so if your data can't pass validation, it will not be written anyway.

How do I handle POST data in Express.js?

I am currently consistently getting 500 errors from Express.js that I believe hinge on a failure to obtain a string key that the request hinges on.
On the client side, I have several requests hitting the same point (/restore), all of which are intended to make "key" a field in a jQuery.ajax() call's data dictionary, included in turn in the main dictionary. On the client-side, I have the following, which includes localStorage fallback that I don't think is particularly relevant:
var restore = function(key, default_value, state, callback)
{
populate_state(state, default_value);
state.initialized = false;
var complete = function(jqxhr)
{
if (jqxhr.responseText === 'undefined')
{
}
else
{
populate_state(state, JSON.parse(jqxhr.responseText));
}
callback();
state.initialized = true;
}
jQuery.ajax('/restore',
{
'complete': complete,
'data':
{
'key': key,
'userid': userid
},
'method': 'POST',
});
if (Modernizr.localstorage)
{
if (localStorage[key] === null || localStorage[key]
=== undefined)
{
return default_value;
}
else
{
return JSON.parse(localStorage[key]);
}
}
else
{
return default_value;
}
}
restore('Calendar', default_value,
default_value, function()
{
jQuery('#submit-calendar').prop('disabled', false);
});
restore('Scratchpad', '', result, function()
{
for(var instance in CKEDITOR.instances)
{
if (CKEDITOR.instances[instance])
{
CKEDITOR.instances[instance].setReadOnly(false);
}
}
});
return restore('Todo', {
'items': [],
'text': ''
},
{
'items': [],
'text': ''
},
function()
{
jQuery('#add-activity-button').prop('disabled', false);
jQuery('#todo-new-entries').prop('disabled', false);
});
return restore('YouPick', {
start_time: new Date().getTime()
},
{
start_time: new Date().getTime()
},
function()
{
});
Note that each call to restore() explicitly specifies a nonempty, unique, alphabetic string for the key as the first argument.
On the server side, Express's routes/index.js has a view that is servicing the request:
router.post('/restore', function(request, response, next)
{
console.log('router.post /restore');
console.log('Query: ' + request.query);
console.log('href: ' + sanitize(request.user.href));
console.log('key: ' + sanitize(request.query.key));
var result = look_up_key(request.user.href, request.query.key);
console.log(result);
response.type('application/json');
response.send(result);
});
The sanitize function wipes out characters that are not alphanumeric or an explicitly enumerated punctuation character. It should have no request on the purely alphabetic key.
This, with the multiple calls, has an output for /bin/www of:
router.post /restore
Query: [object Object]
href: httpsapi.stormpath.comv1accounts**********************
POST /restore 500 39.516 ms - 1210
router.post /restore
Query: [object Object]
href: httpsapi.stormpath.comv1accounts**********************
POST /restore 500 5.000 ms - 1210
router.post /restore
Query: [object Object]
href: httpsapi.stormpath.comv1accounts**********************
POST /restore 500 5.842 ms - 1210
It looks like there is something there for the query, but where do I access it? http://expressjs.com/api.html seems like I should be able to treat it as a dictionary, but among the server-side console.log() calls, console.log('key: ' + sanitize(request.query.key)); does not appear to be producing any output, even an empty or corrupt key. It appears to crash there, apparently sending a 500 from there.
I could probably, or at least possibly, circumvent the issue by encoding and decoding data as JSON, and while I think that's generally a winning solution, I would like to understand why this is not working.
I also don't think that key is someone's reserved word; a global, hand-inspected search and replace from key to identifier seemed not to observably alter the behavior.
So two questions, in order of preference:
1: How can I send and receive variables that will be interpreted as putting things into a GET or POST query string, or taking them out of the same? And what is the [Object object] represented by request.query?
2: If that's not the route to take, and I should just use JSON, what (if anything) should I know about JSON encoding in this exact context? Is it as simple as JSON is normally, or are there things I should be advised of?
Thanks,
With POST requests, data is usually passed in the request body, which means that you need to use req.body instead of req.query (the latter is used to access the data passed in the query string of a URL). Before req.body works, you need to include the body-parser middleware.
As for why [object Object] is being logged: this has to do with stringification. Your log command uses + to "add" a string and an object (request.query), which will use the string representation of an object and that happens to be [object Object].
Instead, you should pass objects are separate arguments to console.log():
console.log('Query: ', request.query); // comma instead of plus
That will show a more elaborate string representation of the object. Alternatively, you can even have it print out as JSON:
console.log('Query: %j', request.query)

Parse CloudCode order of execution

Im trying to send a push message to everyone with read access every time a new note is saved.
In pseudocode it should get the ACL. Evaluate each member in the ACL and return an array of all users with read access. Then send a push notification to each member.
I've tried running separate task one by one and it works properly. However when I put everything together in the following code I get strange results. Looking at the log I can see it not executing in order as I expect. I first though the getACL call was an asynchronous call so I tried to implement promises with no luck. Then after help from stackoverflow I find out that getACL is not asynchronous therefore the code should just work, right?
This is what I'm trying:
Parse.Cloud.afterSave("Notes", function(request) {
var idsToSend = [];
var i = 0;
console.log("1 start");
var objACL = request.object.getACL();
var ACLinJSON = objACL.toJSON();
console.log("2 ACL = " + ACLinJSON);
for (var key in ACLinJSON) {
if (ACLinJSON[key].read == "true") {
idsToSend[i] = key.id;
console.log("3 i = " + i + " = " + idsToSend[i]);
i++;
}
}
console.log("4 idsToSend = " + idsToSend);
//lookup installations
var query = new Parse.Query(Parse.Installation);
query.containedIn('user', idsToSend);
Parse.Push.send({
where: query,
data: {
alert: "note updated"
}
}, {
success: function() {
console.log("Success sent push");
},
error: function(error) {
console.error("can’t find user"); //error
}
});
});
And this is the response I see from parse log
I2014-08-04T08:08:06.708Z]4 idsToSend =
I2014-08-04T08:08:06.712Z]2 ACL = [object Object]
I2014-08-04T08:08:06.714Z]1 start
I2014-08-04T08:08:06.764Z]Success sent push
Everything is completely out of order??
How can I execute the above function in the way it's written?
I've found the logs are not in order when I run things too, could be a timing issue or something, ignore the order when they're in the same second, I have done other tests to confirm things really do run in order on my own Cloud Code... had me completely confused for a while there.
The issue you're having is that log #3 is never being hit... try tracing ACLinJSON on it's own to see the actual structure. When you append it to a string it outputs [object Object] as you have seen, so do console.log(ACLinJSON); instead.
Here's the structure I've seen:
{
"*":{"read":true},
"Administrator":{"write":true}
}
Based on that I would expect your loop to work, but it may have a different level of wrapping.
UPDATE:
Turns out the issue was looking for the string "true" instead of a boolean true, thus the fix is to replace the following line:
// replace this: if (ACLinJSON[key].read == "true") {
if (ACLinJSON[key].read == true) {

Categories