Not able to get nested objects from JSON - javascript

I have tried to get some help on this matter previously, but nothing seems to work. I want to retrieve some nested objects from a REST API.
This is the code that I am using and that should work:
var url = 'XXXXX';
$(function(){
$.getJSON(url, function(data){
$.each(data.paths,function(i,emp){
var b = this.places[0].place_radius;
console.log(b);
});
});
});
However, I get this error message when I try to execute it in a web browser:
25
25
apirest.html:14 Uncaught TypeError: Cannot read property 'place_radius' of undefined
I really appreciate any help!

Here's one way to quickly check a bunch of child elements, and assign the correct value to "b", or false if something didn't exist. Note that if place_radius is falsy (evaluates to bool false, so zero for example) you'll have to use a more careful technique.
$.getJSON(url, function(data){
$.each(data.paths,function(i,emp){
var b = this.places && this.places[0] && this.places[0].place_radius || false;
if (b === false) {
console.log("that thing did not exist");
} else {
console.log(b);
}
});
});

Related

Unable to access tags in API data.

I've successfully accessed data from a request to an API.
I have set the data as a var weatherData
If I print out weatherData, I get this whole blob here.
{"coord":{"lon":-79.42,"lat":43.7},"weather":[{"id":701,"main":"Mist","description":"mist","icon":"50n"},{"id":500,"main":"Rain","description":"light
rain","icon":"10n"}],"base":"stations","main":{"temp":286.46,"pressure":1006,"humidity":100,"temp_min":285.15,"temp_max":288.15},"visibility":1207,"wind":{"speed":3.1,"deg":240},"clouds":{"all":90},"dt":1509943080,"sys":{"type":1,"id":3721,"message":0.1665,"country":"CA","sunrise":1509969642,"sunset":1510005682},"id":6167865,"name":"Toronto","cod":200}
The city is what I'm interested in.
I've tried accessing it with weatherData.name but it returns as undefined. What am I doing wrong here?
Just a little add on, incase you can't figure out the return result is JSON or string, this will always be a good snippet to use (In fact I include it on all my projects)
It will try to parse as a JSON and if it failed, it will return undefined.
function tryJSON(x) {
try {
x = JSON.parse(x);
} catch (e) {}
if ((!!x) && (x.constructor === Object)) {
return x;
}
}
console.log(tryJSON('{ "apple": 10 }'));
console.log(tryJSON("{ :notJSON }"));
console.log(tryJSON({ orange: 5 }));

assigning variables only if undefined in javascript

I'm trying to extract two keywords from a url in this format
localhost:3000/"charactername"/"realmname"
where I want to exctract "charactername" and "realmname" and assign them to variables.
I use:
var charactername = req.url.split("/")[1];
console.log(charactername);
var realmname = req.url.split("/")[2];
console.log(realmname);
Everything works fine and dandy at first, but then it seems a request is made for a "favicon.ico", and my variables become undefined since there is a new request url. I tried solving this by encapsulating the code snippet in an if statement like this:
if(req.url !== '/favicon.ico'){
var charactername = req.url.split("/")[1];
console.log(charactername);
var realmname = req.url.split("/")[2];
console.log(realmname);
}
The console.log outputs tells me the variables are set to their correct values, it never says it is undefined so it seems to work.. However, when the next part of the code is executed:
if(charactername.length > 0){
res.writeHead(200, {'Content-Type': 'text/html'});
renderer.view("header", {}, res);
//get json from battle.net
var characterProfile = new Profile(charactername, realmname);
//on "end"
characterProfile.on("end", function(profileJSON){
//Show profile
//Store values we need
var values = {
avatarURL: profileJSON.thumbnail,
charactername: profileJSON.name,
realmname: profileJSON.realm,
level: profileJSON.level
}
//Simple response
renderer.view("profile", values, res);
renderer.view("footer", {}, res);
res.end();
});
I get an error saying cannot read property length of undefined. So it seems the variables become undefined somehow anyway. Anyone got a clue on how to solve this?
if(x === undefined){
//do something
}
This checks if the variable is undefined, however I suggest you check what is causing the error in the first place.
if(charactername && charactername.length > 0){
...

Javascript Variable Sometimes Undefined

I know this question has been asked several times, but I couldn't seem to find a solution that worked for me in any of the previous questions. I have a variable that gets set when my HTML page is done loading, but sometimes when my code tries to access that variable, it says that it is undefined. I'm not sure why, since I believe I am waiting for everything to load properly. This exception seems to happen randomly, as most of the time all the code runs fine. Here's a simplified version of my code:
var globalVar;
function initStuff(filePath) {
// I wait till the HTML page is fully loaded before doing anything
$(document).ready(function(){
var video = document.getElementById("videoElementID");
// My parseFile() function seems to run smoothly
var arrayOfStuff = parseFile(filePath);
if (arrayOfStuff == null) {
console.error("Unable to properly parse the file.");
} else {
setGlobalVariable(arrayOfStuff);
video.addEventListener("play", updateVideoFrame, false);
}
});
}
function setGlobalVariable(arrayOfStuff) {
window.globalVar = arrayOfStuff;
}
function updateVideoFrame() {
// A bunch of other code happens first
// This is the line that fails occasionally, saying
// "window.globalVar[0].aProperty.anArray[0] is undefined"
var test = window.globalVar[0].aProperty.anArray[0].aProperty;
}
The only thing that I can think of that might be causing this problem is some sort of synchronicity issue. I don't see why that would be the case, though. Help please!
Edit:
In case the asynchronicity issue is coming from my parseFile(xmlFile) method, here is what I'm doing there. I thought it couldn't possibly be causing the issue, since I force the method to happen synchronously, but in case I'm wrong, here it is:
function parseKML(xmlFile) {
var arrayOfStuff = new Array();
// Turn the AJAX asynchronicity off for the following GET command
$.ajaxSetup( { async : false } );
// Open the XML file
$.get(xmlFile, {}, function(xml) {
var doc = $("Document", xml);
// Code for parsing the XML file is here
// arrayOfStuff() gets populated here
});
// Once I'm done processing the XML file, I turn asynchronicity back on, since that is AJAX's default state
$.ajaxSetup( { async : true } );
return arrayOfStuff;
}
The first thing you should do in your code is figure out which part of:
window.globalVar[0].aProperty.anArray[0]
is undefined.
Since you have multiple chained property references and array references, it could be many different places in the chain. I'd suggest either set a breakpoint right before your reference it examine what's in it or use several console.log() statement sto output each nested piece of the structure in order to find out where your problem is.
console.log("globalVar = " + globalVar);
console.log("globalVar[0] = " + globalVar[0]);
console.log("globalVar[0].aProperty = " + globalVar[0].aProperty);
console.log("globalVar[0].aProperty.anArray = " + globalVar[0].aProperty.anArray);
console.log("globalVar[0].aProperty.anArray[0] = " + globalVar[0].aProperty.anArray[0]);
If the problem is that globalVar isn't yet set, then you have a timing problem or an initialization problem.
If the problem is that one of the other properties isn't set, then you aren't initializing globalVar with what you think you are.
You may also want to write your code more defensibly so it fails gracefully if some of your data isn't set properly.
You need to use defensive programming.
http://www.javascriptref.com/pdf/ch23_ed2.pdf
Example:
var video = document.getElementById("videoElementID") || 0;
-
if( video && video.addEventListener ){
video.addEventListener("play", updateVideoFrame, false);
}
Here's another version of your code.
window.globalVar = globalVar || [];
function setGlobalVariable(arrayOfStuff) {
window.globalVar = arrayOfStuff;
}
function updateVideoFrame() {
// A bunch of other code happens first
// This is the line that fails occasionally, saying
// "window.globalVar[0].aProperty.anArray[0] is undefined"
if( window.globalVar ){
var g = window.globalVar || [];
var d = (g[0] || {})["aProperty"];
// etc...
}else{
console.error( "test error." );
}
}
function initStuff(filePath) {
// I wait till the HTML page is fully loaded before doing anything
$(document).ready(function () {
var video = $("#videoElementID");
// My parseFile() function seems to run smoothly
var arrayOfStuff = parseFile(filePath) || [];
if (arrayOfStuff == null || video == null ) {
console.error("Unable to properly parse the file.");
} else {
setGlobalVariable(arrayOfStuff);
video.bind("play", updateVideoFrame);
}
});
}

JS: Using variable names to call function

Im working with jQuery. I have an app that makes ajax requests to server that responds with JSON.
in some cases the response from the server will indicate the name of a JS function to be called
{"responseType":"callback", "callback":"STUFF.TestCallback","callbackData":"this is in the callback"}
If the responseType is "callback" as above the JSON is passed to a function to handle this response type. (the var "response" contains the JSON above)
STUFF.callback = function(response){
if(typeof response.callback =='function'){
console.log("All Good")
response.callback(response);
}else{
console.log("Hmm... Cant find function",response.callback );
}
}
STUFF.TestCallBack = function(data){
alert("it worked");
}
But when I do this I get the error "response.callback is not a function".
Any comments on why this is not working and how to do this properly would be greatly appreciated.
A String is a String, not a Function.
response.callback() doesn't work because it is the same as "STUFF.TestCallback"() not STUFF.TestCallback()
You probably want to have the data structured something more like "callback": "TestCallback" then then do:
STUFF[response.callback](response);
Here you use the String to access a property of STUFF. (foo.bar and foo['bar'] being equivalent.)
You could transform that "namespace.func" into a call like this:
STUFF.callback = function(response) {
var fn = response.callback.split("."), func = window;
while(func && fn.length) { func = func[fn.shift()]; }
if(typeof func == 'function') {
console.log("All Good")
func(response);
} else{
console.log("Hmm... Cant find function", response.callback);
}
}
What this does it grab the function by getting window["STUFF"] then window["STUFF"]["TestCallback"] as it loops, checking if each level is defined as it goes to prevent error. Note that this works for any level function as well, for example "STUFF.One.Two.func" will work as well.
You propably could do
var myfunction = eval(response.callback);
myfunction(response);
although using eval() is considered as a bad style by some javascript developers.

JSON/PrototypeJS - why does this only work SOMETIMES?

This is driving me nuts!
I'm getting some JSON from my server:
{"id262":{"done":null,"status":null,"verfall":null,"id":262,"bid":20044,"art":"owner","uid":"demo02","aktion":null,"termin_datum":null,"docid":null,"gruppenid":null,"news":"newsstring","datum":"11.06.2010","header":"headerstring","for_uid":"demo01"},
"id263":{"done":null,"status":"pending","verfall":null,"bid":20044,"id":263,"uid":"demo02","art":"foo","aktion":"dosomething","termin_datum":"11.06.2010","docid":null,"gruppenid":null,"datum":"11.06.2010","news":"newsstring","for_uid":"demo01","header":"headerstring"},
"id261":{"done":null,"status":null,"verfall":null,"id":261,"bid":20044,"art":"termin","uid":"demo02","aktion":null,"termin_datum":"25.06.2010","docid":null,"gruppenid":null,"news":"newsstring","datum":"11.06.2010","header":"headerstring","for_uid":null}}
This is how my JS looks like:
var user = 'demo02';
new Ajax.Request('myscript.pl?someparameter=value', { method:'get',
onSuccess: function(transport){
var db_json = transport.responseText.evalJSON(),
propCount = 0,
someArray1 = [],
someArray2 = [],
otherArray = [];
//JSON DEBUG
console.log('validated string:');
console.log(transport.responseText.evalJSON(true));
for(var prop in db_json) {
propCount++;
if ( (db_json[prop].art == 'foo') && (db_json[prop].for_uid == user) ) {
someArray1.push(db_json[prop]);
} else if( (db_json[prop].art == 'foo') && (db_json[prop].uid == user) ) {
someArray2.push(db_json[prop]);
} else if( db_json[prop].art == 'log' ) {
otherArray.push(db_json[prop]);
}
}
if(someArray1.length>0) {
someArray1.map(function(el){
$('someArray1target').innerHTML += el.done;
//do more stuff
});
}
if(someArray2.length>0) {
someArray2.map(function(el){
$('someArray2target').innerHTML += el.done;
//do more stuff
});
}
});
Sometimes, it works perfectly.
Sometimes, i get my JSON String (it appears in Firebug's "answer"-tab), but it won't log the JSON in console-log(). I'm not getting any errors and javascript is still working.
Next time after reloading, it might work, but it might not.
I cannot remotely imagine why this only happens sometimes!
You are calling evalJSON twice, actually with different parameters each time.
Normally, I wouldn't expect this to have any side-effects, and indeed the prototype documentations for this method don't mention any. However, I remember that earlier versions of firebug were known to manipulate the XMLHttpRequest in weird ways (in order to capture the data going in and out), so maybe this is still relevant today.
Try changing the log statement to this instead:
console.log(db_json);
I found the answer. It makes me want to slam my head. My $('someArray1target') div sometimes was not loaded yet.
I was so focused in finding something weird in my JSON instead of searching for the more obvious, "standard" errors.

Categories

Resources