Unexpected token < in JSON at position 0 in overpass api request - javascript

I'm using overpass api to fetch informations about hospitals in a certain area.
This is the url I use to get the data:
https://overpass-api.de/api/interpreter?data=[out:json][timeout:25];(node[amenity=hospital](41.862018386633096,12.380561828613283,41.9435317956981,12.612133026123049);way[amenity=hospital](41.862018386633096,12.380561828613283,41.9435317956981,12.612133026123049););out;
Since the hospitals can be also way other than simple nodes, I have to treat them differently so I do this:
fetch(url).then(response => {
return response.json();
}).then(results => {
results.elements.forEach(e => {
console.log('Name '+e.tags["name"])
if(e.type == "way"){
console.log('ID: ' + e.id)
let urlWay = `https://overpass-api.de/api/interpreter?data=[out:json][timeout:25];(way[amenity=hospital](${e.id}););out%20center%20meta;`;
fetch(urlWay).then(response=> {
return response.json()
}).then(result => {
lat = result.elements[0].center["lat"]
lon = result.elements[0].center["lon"]
})
} else {
//get lat lon info normally
}
Then I use lat and lon to put a marker on the map.
The explanation for this is that a "way" does not have a single lat-lon information, but it is formed by several nodes. This is an example:
{
"type": "way",
"id": 107248762,
"nodes": [
1233017145,
1233017732,
1233017520,
1233017183,
1233018290,
2144891055,
1233017895,
1233017145
],
"tags": {
"amenity": "hospital",
"wheelchair": "yes"
}
},
So, to get the lat lon informations, I use the "id" property to get the center of the building, by using the urlWay in the code above, specifying out center meta. I use elements[0] because the array has only one element. You can see an example of output by clicking here.
The problem is that, at some point while fetching the informations about the ways and putting markers on the map, the program stops and gives me the error:
SyntaxError: Unexpected token < in JSON at position 0 in overpass api request
I'm assuming (don't know if I'm right) that there is one of these JSON files I get that is not correctly written, so I'm wondering how can I prevent this exception, maybe by just ignoring a bad formatted file.
EDIT: I've modified the code as proposed by user mmd in the answers and worked correctly, so it probably was an error linked to rate limiting.

The issue is most likely related to rate limiting or other error conditions, in which case you receive an XML formatted error message, albeit the HTTP status code might still be HTTP 200! This message cannot be parsed as JSON string, hence the error message.
In general, your approach to query Overpass API one-by-one is quite inefficient. Instead you can also provide several Ids in one go. It is highly recommended to bundle requests this way, rather than sending one request for each single ID, which severely increases chances to hit rate limiting.
way(id:1000,1002,1003,1004)[amenity=hospital]
In wonder, why you don't use out:center in your original query get get all details on one go.
[out:json][timeout:25];
(node[amenity=hospital](41.862018386633096,12.380561828613283,41.9435317956981,12.612133026123049);
way[amenity=hospital](41.862018386633096,12.380561828613283,41.9435317956981,12.612133026123049););
out center;

After some time the api throws 429 Too Many Requests Error.
Try addind some timeout to your api calls.

Related

Parsing a String of JSON for attribute into multiple sends to the same endpoint

My problem seems simple but I've hit a wall looking into it. Unfortunately, I'm not too terribly deep into javascript but I understand its going to require it. Basically, I'm having one service do a GET on a server that provides all of the information into a bulk drop. I can take all the attributes that qualify and combine them into a single json string.
I need to pass that string to another platform that will divide the attribute into multiple sends and post to an endpoint.
The database I'm posting to (at the moment) cannot handle bulk uploads so this seems to be the best option, but I'm not sure if its possible.
{
"email_address": ["jon#gmail.com", "sally#yahoo.com", "bobbert#msn.com"]
}
Into
[
{"email_address":"john#gmail.com"},
{"email_address":"sally#yahoo.com"},
{"email_address":"bobbert#msn.com"}
]
Any help is appreciated!
[Edit: Quickly made a change to the sample code above. Meant for it to be an array of email address & forgot to format it correctly]
I am not sure about your object structure but you can use something like this.
let obj = {
email_address: ["jon#gmail.com", "sally#yahoo.com", "bobbert#msn.com"],
};
let objects = [];
for (key in obj) {
if (Array.isArray(obj[key])) {
for (val of obj[key]) {
objects.push({
[key]: val
});
}
}
}
console.log(objects);

Need Help to implement Tincan Javascript API

I'm working on tincan JavaScript API. The issue my data format is total change and TinCan have specified a why to pass data along with call. Help me to adjust my data in TinCan Api format. Here is sample data one of my call.
var data = {
"groupId": "groupId",
"groupName": "gNameEncrypt",
"tutorNames": "tutorNames",
"actorNames": "actorNames",
"otherNames": "otherNames"
};
Current what i do i simply decode this data and send it like this.
var actionList = new TinCan(
{
recordStores: [{
endpoint: "http://example.com",
username: username,
password: password,
allowFail: false
}]
});
var action = new TinCan.Agent({
"name": "insert"
});
actionList.getStatements({
'params': {
'agent': action,
'verb': {
'id': $.base64.encode(data)
}
},
'callback': function (err, data) {
console.info(data.more);
var urlref = "http://<?php echo $_SERVER['SERVER_NAME'] . ":" . $_SERVER['SERVER_PORT'] . $uriParts[0] . "?" ?>t=" + data.more.TutorToken;
window.location.href = urlref;
}
});
crypt.finish();
});
There are really two parts here:
need to get data into an xAPI (formerly Tin Can) format, and
the code itself.
In depth,
I think you need to take another look at how xAPI is used in general. Data is stored a JSON "Statement" object that has 3 required properties and various other optional ones. These properties often contain complex objects that are very extensible. It is hard to tell from what you've shown what you are really trying to capture and what the best approach would be. I suggest reading some material about the xAPI statement format. http://experienceapi.com/statements-101/ is a good starting point, and to get at least some coverage of all the possibilities continue with http://experienceapi.com/statements/ .
The code you've listed is attempting to get already stored statements based on two parameters rather than trying to store a statement. The two parameters being "agent" and "verb". In this case We can't tell what the verb is supposed to be since we don't know what data contains, I suspect this isn't going to make sense as a verb which is intended to be the action of a statement. Having said that the fact that the "actor" has a value of action is questionable, as that really sounds more like what a "verb" should contain. Getting the statements right as part of #1 should make obvious how you would retrieve those statements. As far as storing those statements, if you're using the TinCan interface object you would need to use the sendStatement method of that object. But this interface is no longer recommended, the recommended practice is to construct a TinCan.LRS object and interact directly with it, in which case you'd be using the saveStatement method.
I would recommend looking at the "Basic Usage" section of the project home page here: http://rusticisoftware.github.io/TinCanJS/ for more specifics look at the API doc: http://rusticisoftware.github.io/TinCanJS/doc/api/latest/

Detect when no previous posts available in Facebook Graph posts edge?

I'm accessing the Facebook Graph API for posts and am trying to figure out the pagination handling. I understand the use of paging.next and paging.previous properties of the results but I'd like to know when there are actually previous results. Particularly, when I make the first 'posts' call, I get back a paging.previous url even though there are no previous values. Upon calling that url I get a response with no results.
For example, calling "168073773388372/posts?limit=2" returns the following:
{
"data": [
{
"story": "Verticalmotion test added a new photo.",
"created_time": "2015-12-02T17:04:56+0000",
"id": "168073773388372_442952469233833"
},
{
"message": "http://www.youtube.com/watch?v=QD2Rdeo8vuE",
"created_time": "2013-12-16T23:19:30+0000",
"id": "168073773388372_184840215045061"
}
],
"paging": {
"previous": "https://graph.facebook.com/v2.6/168073773388372/posts?limit=2&format=json&since=1449075896&access_token=****&__paging_token=enc_AdA69SApv4VoBZB0PPZA7W5EivCYQal8KMFmRNkyhr8ZBk4w0YmFEQUJWV3JZBS70ihyMpbqieQaERhY50enqNCMBuIZATadeopYj8xPvQL7Y8KueaQZDZD&__previous=1",
"next": "https://graph.facebook.com/v2.6/168073773388372/posts?limit=2&format=json&access_token=****&until=1387235970&__paging_token=enc_AdAVMaUlPmpxjBmq5ZClVdNpFp7f9MyMFWjE7ygqsMLW7zvSx3eGHLkfwDxdCx0uO3ooAZCKDmCwMWHZA9RNyxkYUPJyjMtO3kynKm5uF2PhoPZB2gZDZD"
}
}
How can I tell if it's the first set of results?
From tidbits scattered around the documentation and web, it seems like the previous url shouldn't be there.
I don't think it matters because I get the same results in the Graph Explorer but I'm using OpenFB to access the API.
You can set the order to be reverse then get the 1st result
https://developers.facebook.com/docs/graph-api/using-graph-api
Ordering
You can order certain data sets chronologically. For example you may sort a photo's comments in reverse chronological order using the key reverse_chronological:
GET graph.facebook.com
/{photo-id}?
fields=comments.order(reverse_chronological)
order must be one of the following values:
*chronological*
*reverse_chronological*

webOS/Ares : read JSON from URL, assign to label

I've used the webOS Ares tool to create a relatively simple App. It displays an image and underneath the image are two labels. One is static, and the other label should be updated with new information by tapping the image.
When I tap the image, I wish to obtain a JSON object via a URL (http://jonathanstark.com/card/api/latest). The typcial JSON that is returned looks like this:
{"balance":{"amount":"0","amount_formatted":"$0.00","balance_id":"28087","created_at":"2011-08-09T12:17:02-0700","message":"My balance is $0.00 as of Aug 9th at 3:17pm EDT (America\/New_York)"}}
I want to parse the JSON's "amount_formatted" field and assign the result to the dynamic label (called cardBalance in main-chrome.js). I know that the JSON should return a single object, per the API.
If that goes well, I will create an additional label and convert/assign the "created_at" field to an additional label, but I want to walk before I run.
I'm having some trouble using AJAX to get the JSON, parse the JSON, and assign a string to one of the labels.
After I get this working, I plan to see if I can load this result on the application's load instead of first requiring the user to tap.
So far, this is my code in the main-assistant.js file. jCard is the image.
Code:
function MainAssistant(argFromPusher) {}
MainAssistant.prototype = {
setup: function() {
Ares.setupSceneAssistant(this);
},
cleanup: function() {
Ares.cleanupSceneAssistant(this);
},
giveCoffeeTap: function(inSender, event) {
window.location = "http://jonathanstark.com/card/#give-a-coffee";
},
jcardImageTap: function(inSender, event) {
//get "amount_formatted" in JSON from http://jonathanstark.com/card/api/latest
//and assign it to the "updatedBalance" label.
// I need to use Ajax.Request here.
Mojo.Log.info("Requesting latest card balance from Jonathan's Card");
var balanceRequest = new Ajax.Request("http://jonathanstark.com/card/api/latest", {
method: 'get',
evalJSON: 'false',
onSuccess: this.balanceRequestSuccess.bind(this),
onFailure: this.balanceRequestFailure.bind(this)
});
//After I can get the balance working, also get "created_at", parse it, and reformat it in the local time prefs.
},
//Test
balanceRequestSuccess: function(balanceResponse) {
//Chrome says that the page is returning X-JSON.
balanceJSON = balanceResponse.headerJSON;
var balanceAmtFromWeb = balanceJSON.getElementsByTagName("amount_formatted");
Mojo.Log.info(balanceAmtFromWeb[0]);
//The label I wish to update is named "updatedBalance" in main-chrome.js
updatedBalance.label = balanceAmtFromWeb[0];
},
balanceRequestFailure: function(balanceResponse) {
Mojo.Log.info("Failed to get the card balance: " + balanceResponse.getAllHeaders());
Mojo.Log.info(balanceResponse.responseText);
Mojo.Controller.errorDialog("Failed to load the latest card balance.");
},
//End test
btnGiveCoffeeTap: function(inSender, event) {
window.location = "http://jonathanstark.com/card/#give-a-coffee";
}
};
Here is a screenshot of the application running in the Chrome browser:
In the browser, I get some additional errors that weren't present in the Ares log viewer:
XMLHttpRequest cannot load http://jonathanstark.com/card/api/latest. Origin https://ares.palm.com is not allowed by Access-Control-Allow-Origin.
and
Refused to get unsafe header "X-JSON"
Any assistance is appreciated.
Ajax is the right tool for the job. Since webOS comes packaged with the Prototype library, try using it's Ajax.Request function to do the job. To see some examples of it, you can check out the source code to a webOS app I wrote, Plogger, that accesses Blogger on webOS using Ajax calls. In particular, the source for my post-list-assistant is probably the cleanest to look at to get the idea.
Ajax is pretty much the way you want to get data, even if it sometimes feels like overkill, since it's one of the few ways you can get asynchronous behavior in JavaScript. Otherwise you'd end up with code that hangs the interface while waiting on a response from a server (JavaScript is single threaded).

Definitive reference for Google Maps Placemark object

I am using the following method to reverse geocode a google maps latlng:
[GClientGeocoder.getLocations(address:String, callback:function)][1]
Which states as follows:
As this method requires a call to a Google server, you must also pass a callback method to handle the response. This response will contain a Status code, and if successful, one or more Placemark objects.
Can anyone point me to a definitive reference of what a Placemark object is as it seems to return different attributes for different locations. e.g. sometimes I get a ThoroughfareName and others an AddressLine. I would like to understand if I will always get one or other of them and whether they are interchangeable.
This page is from the Google Maps API documentation, and contains a pretty straightforward explanation of what a Placemark object is.
However, the part you probably want to focus on is where it states what format Google uses for the AddressDetails object in a Placemark, which is xAL (eXtensible Address Language). There is a link to the spec there, which leads to a downloadable schema (xsd file), which essentially defines the entire format. A word of warning: the spec is pretty extensive, but you may not need to worry about a great deal of it for your project.
EDIT:
Apologies for not being allowed to add links to the relevant pages for you.
You have to hunt for it, but Google does in fact have some documentation about Placemarks hidden away.
The contents of the Placemark object do vary based on the data available. I found the best way to work out what I was getting back was to use JSON.stringify to examine the response (for debugging):
function onGeocode (resp)
{
document.getElementById("cd_output").innerHTML = JSON.stringify (resp);
}
This gave me the following results when I GeoCoded an address in Sydney, Australia:
Placemark
{
id, address,
AddressDetails
{
Country, CountryNameCode, CountryName,
AdministrativeArea
{
AdministrativeAreaName,
Locality
{
LocalityName
Thoroughfare { ThoroughfareName }
PostalCode { PostalCodeNumber }
}
}
}
Accuracy,
ExtendedData
{
LatLonBox { north,south,east,west }
Point { coordinates }
}
}

Categories

Resources