I need to do a lookup onto an itunes url which throws the json, in my nodejs based backend, i am using requests module of nodejs to get the json, and it indeed returns me the json as well, but the moment i try parsing it doesn't return me internal objects, however calls like stringify or JSON.parse just work without any exception.
sample url https://itunes.apple.com/lookup?id=477091027
//sample url https://itunes.apple.com/lookup?id=477091027
request(itunesUrl, function (error, response, body) {
if (!error && response.statusCode == 200) {
var jsonbody = JSON.stringify(body.trim());
var obj = JSON.parse(jsonbody);
console.log(obj);
/*for(var myKey in obj)
{
console.log("key:"+myKey+", value:"+obj[myKey]);
}*/
//none of these show value in them
appinfo.appname = obj.results[0].trackName;
appinfo.appImage = obj.results[0].artworkUrl60;
appinfo.appCategory = obj.results[0].genres[0];
}
});
I am at my wits end now
Actually, you are stringifying the json before parse-ing it again :
var jsonbody = JSON.stringify(body.trim());
var obj = JSON.parse(jsonbody);
If body is supposed to contain json, then you directly should do
var obj = JSON.parse(body);
you just need to add the parameter json:true
request({url:itunesUrl, json:true}, function (error, response, body) {
if (!error && response.statusCode == 200) {
console.log(body.results[0].trackName)
}
});
Even though Ninetainedo's answer looks correct, the docs suggest that you can use json: true as a parameter in the request options. This will automatically parse the json into a object, removing the need for the JSON.parse() line.
See https://github.com/request/request#requestoptions-callback
Related
I am unable to access a simple JSON Element from a JSON Structure that looks like:
{
"ACTION": "AA",
"MESSAGE": "Customer: 30xxx Already Approved on 2017/01/01"
}
I get the data in JSON Format but when i do data.ACTION or data.MESSAGE i get Undefined as the output.
By doing case sensitive also, its not working( Image attached )
var url = base + query;
var getJSON = function (url) {
return new Promise(function (resolve, reject) {
var xhr = new XMLHttpRequest();
xhr.open('get', url, true);
xhr.withCredentials = true;
xhr.onload = function () {
var status = xhr.status;
if (status == 200) {
resolve(xhr.response);
} else {
reject(status);
}
};
xhr.send();
});
};
getJSON(url).then(function (data) {
console.log(data); //Getting JSON Data
var output = JSON.stringify(data);
var obj = JSON.parse(output.replace(/ 0+(?![\. }])/g, ' '));
console.log(output);
console.log(obj.message); //Here getting UNDEFINED
}, function (status) { //error detection....
alert('Something went wrong.');
});
Console:
{"ACTION":"AA","MESSAGE":"Customer No. 0000030332 Already Approved On 20170113"}
stringify returns the following
{\"ACTION\":\"AA\",\"MESSAGE\":\"Customer No. 0000030332 Already Approved On 20170113\"}"
EDITED. I first thought the error was due to parsing, given the print. -.-
Solution:
When you print the output, obj it's still a string, not an object. So it is OK at that point.
Your "undefined" property message should be replaced by MESSAGE.
Instead of console.log(obj.message); just use console.log(obj.MESSAGE);
Also. An example of parsing JSON:
var myJson = '{"ACTION":"AA","MESSAGE":"Customer No. 0000030332 Already Approved On 20170113"}';
console.log(myJson); // This prints the literal string
console.log(JSON.parse(myJson)); // this prints an "object"
obj.message property is not defined and when you try to get the property which is not defined on an object, you get undefined.
Javascript is case sensitive. You should try obj.MESSAGE instead to get the property value. Also, to check if a property exists on an object you can make use of object.hasOwnProperty([propName]) method to check if a property exists on a object or not.
EDIT 1: Try running the following code snippet. JSON data string is parsed before accessing the property.
var jsonString = "{\"ACTION\":\"AA\",\"MESSAGE\":\"Customer No. 0000030332 Already Approved On 20170113\"}";
var obj = JSON.parse(jsonString);
console.log(obj.MESSAGE);
data already is a JSON string, there's no need to JSON.stringify it (which returns a string with a JSON-encoded string literal). Parsing it into output only leads to a string again, which has no properties. You should use
console.log(data);
var obj = JSON.parse(data);
console.log(obj);
obj.MESSAGE = obj.MESSAGE.replace(/ 0+(?![\. }])/g, ' ');
(notice the proper casing of the property name)
You can try:
var jsonObject = data.data;
console.log(jsonObject.ACTION)
I'm trying to process the returned JSON result from the request
so I need to expand its scope outside this request call.
To do that I declared data variable with an empty string and assign the result to this data but it doesn't print the result.
How can I accomplish this?
module.exports = function(callback) {
var request = require("request")
var url = "http://sheetsu.com/apis/94dc0db4"
var data = "";
request({
url: url,
json: true
}, function (error, response, body) {
if (!error && response.statusCode === 200) {
callback(body)
data = body;
}
})
console.log(data);
}
This is classic async confusion : your console.log call will happen before the http request callback.
Your script is executed in this order:
request() is executed
console.log(data)
request() callback function, where you asign data a value
If you want to print data, you must do it inside the request callback function. The async module, is very useful when performing async tasks, specially if you need to perform tasks in a specific order and use the data from this requests.
I'm a bit of a newbie to NodeJS, but I've looked around all over and can't seem to find a solution to my problem below. I'm sure it's something simple, but thanks in advance for all help you can give me!
I'm trying to make a simple JSON scraper via NodeJS. All I need is for JSON to be stored to a variable. The problem is, I'm using Require, and their example just logs it to console. I've tried adding a variable after it's logging to the console, but I'm just getting undefined. Here's my code below, it's pretty simplistic so far :)
// var jsonVariable; Doesn't work, shown as a test
function getJSON(url){
var request = require("request")
request({
url: url,
json: true
}, function (error, response, body) {
if (!error && response.statusCode === 200) {
console.log(body) // Print the json response
//return body; This doesn't work, nor does making a global variable called json and assigning it here. Any ideas?
//jsonVariable = body; // This also doesn't work, returning undefined even after I've called the function with valid JSON
}
})
}
Once again, thanks so much for any help you can give me :)
The problem is that the request method is asynchronous, but you're trying to synchronously return a result. You'll need to either make a synchronous request (which doesn't appear to be possible with the request package you're using), or else pass a callback function to be called when the request responds successfully. e.g.:
var request = require("request")
function getJSON(url, callback) {
request({
url: url,
json: true
}, function (error, response, body) {
if (!error && response.statusCode === 200) {
callback(body);
}
});
}
getJSON('http://example.com/foo.json', function (body) {
console.log('we have the body!', body);
});
If you use 'return body' where does it return to? That function is being called as a parameter to the request() function. You also cannot define a variable in your anonymous function because you will not have access to it outside of that scope.
What you need to do is define a variable outside of function getJSON() and then save body to that.
e.g.,
var result;
function getJSON(url){
var request = require("request")
request({
url: url,
json: true
}, function (error, response, body) {
if (!error && response.statusCode === 200) {
result = body;
}
});
}
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 7 years ago.
I'm still new to Node.JS and I'm trying to call a REST API using GET method.
I use 'request' package from this link. The call actually works but when I try to return the response body from other .JS file, I get 'undefined'.
Here is my 'first.js'
var request = require('request');
var first = function (){
};
first.prototype.getValue = function (value){
var thpath = somePath + value;
var postheaders = {
'Content-Type': 'x-www-form-urlencoded'
};
var options = {
url : 'https://' + thpath,
method : 'GET',
headers : postheaders,
};
var data_rec = "";
request(options, function (error, response, body) {
if (!error && response.statusCode == 200) {
data_rec = JSON.parse(body);
console.info(data_rec);
return data_rec;
} else return "failed to get";
});
};
module.exports = first;
Here is my 'second.js'
var first = require('./first');
var instance = new first();
var val1 = instance.getValue(someValue);
console.info(val1);
The 'console.info(data_rec)' from 'first.js' returns a JSON (which means that the call is working). However, 'console.info(val1)' from 'second.js' returns 'undefined'. Can anybody find the solution?
Update:
I am able to get the solution by using sync-request package.
var val1 = instance.getValue(someValue);
console.info(val1);
instance.getValue is an asynchronous method. Meaning javascript vm wont wait for response, it just goes on with next line ie console.info(val1); Ajax request takes time and response comes in only after some time, and triggers the success function.Till then val1 is undefined
request(options, function (error, response, body) {
if (!error && response.statusCode == 200) {
data_rec = JSON.parse(body);
console.info(data_rec);
return data_rec;
} else return "failed to get";
});
See that console.info(data_rec); is given inside the success function, success function is something that get called after response is successfully retrieved
You're trying to return asynchronous response in a synchronous manner which is not possible.
When you make the call, first() is executed and returned with no value and then async call completes. So console.log prints correctly, but you won't receive the value.
Modify this part of code
request(options, function (error, response, body) {
if (!error && response.statusCode == 200) {
data_rec = JSON.parse(body);
console.info(data_rec);
return data_rec;
} else return "failed to get";
});
to this
var request = request(options, function (error, response, body) {
if (!error && response.statusCode == 200) {
data_rec = JSON.parse(body);
console.info(data_rec);
}
});
return request.then(function (res) {
if (res.statusCode >= 300) {
return "failed to get";
} else {
return res.body.toString()
}
})
This is my front-end code (using fetch)
var MyModel = Backbone.Model.extend();
var MyCollection = Backbone.Collection.extend({
url: '/questions',
model: MyModel
});
var coll = new MyCollection();
coll.fetch({
error: function (collection, response) {
console.log('error', response);
},
success: function (collection, response) {
console.log('success', response);
}
});
and this is my back-end code (using app.get)
app.get('/questions', function (request, response) {
console.log('Inside /questions');
response.writeHead(200, {
'Content-Type': 'text/json'
});
response.write('{test:1}');
response.end();
});
The problem is that although the response is as expected, the client-side error callback is called. When I remove the line response.write('{test:1}');, the success callback is called. Any ideas as to what I might be doing wrong?
Well {test:1} is not valid JSON.
{ "test":"1" }
OR
{ "test":1 }
is however, try one of those instead.
Keys are strings in JSON, and strings in JSON must be wrapped in double quotes check out JSON.org for more information.
To ensure you have valid JSON for more complex objects just use JSON.stringify():
var obj = { test : 1 };
response.write(JSON.stringify(obj)); //returns "{"test":1}"
Also, the correct Content-Type for json is application/json
{test:1} isn't valid JSON, you should try { "test":"1" }.
Another solution is to check Express's render.json function to see how it does sending json to the browser:
https://github.com/visionmedia/express/blob/master/lib/response.js#L152-172
If you're using express you need to res.send will automatically convert objects into JSON. If you're worried about it, there's a new one called res.json that will convert anything into JSON.
var obj = {super: "man"}
res.send(obj) // converts to json
res.json(obj) // also converts to json
You don't need need writeHead(), write(), or end().
http://expressjs.com/guide.html