Using freegeoip for a list of IPs - javascript

Please give me a simple tip where to dig!
I have multiple IP's and need to display the location next to each of them.
I have a list of IPS in array via
var table = document.createElement('table');
table.innerHTML = forext;
var ips = [].slice.call(table.querySelectorAll('a[href*="?ip="]')).map(anchor => anchor.textContent).join("\n");
8.8.8.8
8.8.4.4
...
I can get the location of each of them via input box
$('.send').on('click', function(){
$.getJSON('https://ipapi.co/'+$('.ip').val()+'/json', function(data){
$('.city').text(data.city);
$('.country').text(data.country);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input class="ip" value="8.8.8.8">
<button class="send">Go</button>
<br><br>
<span class="city"></span>,
<span class="country"></span>
BUT what I need is to print the IPs and the location next to it:
So, I have this:
8.8.8.8
8.8.8.8
BUT I need this
8.8.8.8 -Mountain View, US
8.8.8.8 -Mountain View, US
...
How can I proceed the whole array via http://freegeoip.net/json/? Thank you.
Update 1: Trying to make it using: ips[i]
var ipText='Lookup...';
var table = document.createElement('table');
table.innerHTML = forext;
var ips = [].slice.call(table.querySelectorAll('a[href*="?ip="]')).map(anchor => anchor.textContent).join("\n");
var ipLocations = [];
for(i=0;i<ips.length;i++){
$.getJSON('https:/freegeoip.net/json/' + ips[i], function(data) {
// could also use data.country_name, or any other property in the returned JSON
var outputString = data.ips[i] + ' - ' + data.city + ', ' + data.country_code;
ipLocations.push(outputString);
});
}
ipText = ipLocations.join('\n');
message.innerText = ipText;

First of all, you really want your IPs to be an array of strings, not a single string. As such, you should change your declaration for var ips = ... and delete the .join("\n") from the end--that turns your convenient list of IP strings into a single string with the IPs separated by newline characters, which you don't want.
Then, when you have an array of IP addresses of a form something like ips = ['8.8.8.8', '8.8.4.4', ... ];
...then you can get the output you described in the following way:
var ipLocations = [];
for (var ip of ips) {
$.getJSON('https://freegeoip.net/json/' + ip, function(data) {
// could also use data.country_name, or any other property in the returned JSON
var outputString = data.ip + ' - ' + data.city + ', ' + data.country_code;
ipLocations.push(outputString);
});
}
Now you have an array of strings with IP address + location, as you described. If you now want to turn THAT into a single string, you can do ipText = ipLocations.join('\n'); to get the output lines separated by newline characters.
If you're going to be outputting this text into an HTML document though, you might want to join on <br> instead of \n, there are many contexts in which whitespace characters like \n will be ignored and you would end up with all your output on one line.
UPDATE:
There were some very silly mistakes in my original answer, chief among them being that I mixed Python and JavaScript syntax (facepalm). Having fixed them, this code does work. That being said, there are some caveats that need to be mentioned, as well as some errors in your Update 1 code that you should really try to understand.
First, the issues in your code:
You never got rid of the .join("\n") from line 4 where you define ips, so it's still just a string instead of an array of strings. This means that your for-loop is actually looping over each individual character in the ips string, instead of complete IP addresses.
You try to access data.ips[i] inside of the loop. The data variable contains the JSON response to your AJAX request, but automatically converted from a JSON string into an actual JavaScript object by jQuery. It only has the properties that are included in the response. In this case, the response always has an ip property, so you can access data.ip. However, ips is a variable that YOU created--data.ips doesn't exist, so you can't access its indices.
As a side note, if you used the for...of syntax, you would also have a loop variable called ip that you can use instead. However, you need to understand that ip and data.ip are not the same variable, even if they will always have the same value in this case.
The URL starts with "https:/" instead of "https://". This one is actually my fault, I typo'd it in my original answer >_>;
With that out of the way, you brought up a very important point in your comment-- the function $.getJSON() is asynchronous, so (ignoring the other issues) the code as you wrote it in Update 1 will probably not do what you expect. The code after the call to getJSON will keep running even if your AJAX request doesn't have a response yet, so if you immediately access the ipLocs array it might only have some of the output strings yet, or even be empty.
I'm not going to explain how to wait on non-blocking code to you, because that's a completely different question. I'm also worried that it will only make things more confusing, given your apparent level of familiarity with JavaScript. But if you just want a quick solution that gives you the results that you expect, even if it's not at all best practice, then you can use the ajax function instead of getJSON. This allows you to explicitly tell jQuery to send your AJAX request synchronously, meaning it will wait for a response before continuing to run your code. However, you need to be aware that synchronous requests may temporarily lock your browser, preventing any other actions until the request is completed. That version would look like this:
var ipLocations = [];
for (var ip of ips) {
$.ajax({
url: 'https://freegeoip.net/json/' + ip,
async: false,
success: function(data) {
var outputString = data.ip + ' - ' + data.city + ', ' + data.country_code;
ipLocations.push(outputString);
}
});
}

Related

Passing a json array to javascript function in a jade rendered page

I have a json array being passed to a jade template.
This template then runs through the array adding rows to the html output.
However a new requirement no needs that json object to be passed to a javascript function, so I tried:
- var json = JSON.stringify(rows);
input.medium.success.button.error(type='submit', id='update_details', value= sendCommandLabel, onclick='sendCommand(' + json + ')')
which gives the following output (the full array omitted from brevity):
<input type="submit" id="update_details" value="Send Command" onclick="sendCommand([{"id":"id1;,"param1":value1, ... "}])">
Which is not useful as I am want to use this output in the javascript function and as it stands I can't consume it.
I am hoping I am missing something simple as my other option is to recreate the json array by looping through the objects in the renderer to recreate it!
UPDATE: I modified the code so instead of passing the array to the function, the array is hardcoded into the function while the jade page was being compiled. So this:
function sendStopCommandToAllSensors()
{
var hardcode = !{JSON.stringify(rows)};
became
function sendStopCommandToAllSensors()
{
var hardcode = [{"id":"id1", ... }, {"id":"id2", ... }];
But that still didn't work.
Puzzlingly adding a couple of simple alerts in there showed that there was the correct number of objects (later confirmed that there by cutting and pasting the resultant string directly into code and then manually adding a third object).
alert(hardcode.length); // displays 2
alert("rows: " + hardcode); // displays [object Object],[object Object]
Which is why in the loop that follows the
for (var row in hardcode)
{
alert("row: " + row); // displays 0 or 1, not an object
if (row.active == 1)
{
alert("Reached here"); // never reached
the final line is never reached.
UPDATE II: By stringifying hardcode I can output the human readable json.
alert("rows: " + JSON.stringify(hardcode));
Why is the code not seemingly parsing the array correctly and what to I do need to do correct it?
UPDATE III: I now having it working by using a two step traditional loop and assignment.
for (var i=0; i<rows.length; i++)
{
var row = rows[i];
So the question seems to be now, why didn't the for..in loop work as expected?
I am new to this, but I was going through similar problem I think.
But I am totally ok with JSON.stringify method, which was your first solution. It looks ugly in generated hmtl, but I found it useful in my case.
At least I think I understood it right and you are not trying to do some kind of magic what I can't absorb yet.
if
rows=[{id:id,param:param},{id:id2,param:param2}]
JADE:
- var json = JSON.stringify(rows);
input(type='submit', onclick='myFunction(' + json + ')')
JS:
function myFunction(myRows) {
console.log(myRows[0].id);
console.log(myRows[0].param);
console.log(myRows[1].id);
console.log(myRows[1].param);
.
.
at least it is ok in what I am working on.
I hope I didn't wrote pile of nonsense :)

How to list Wikipedia page titles with links using JSON?

This is my current code. It lists out page titles perfectly, but the links all return 'undefined'.
function func(json) {
var e = document.getElementById('wiki');
var i;
for (i=0; i < json.query.allpages.length; i++) {
e.innerHTML += i + ": " + '' + json.query.allpages[i].title + '' + "<br />";
}
}
function getFromWikipedia() {
var txt = document.getElementById('txt');
var e = document.getElementById('wiki');
var o = document.createElement("script");
o.setAttribute("src", "http://en.wikipedia.org/w/api.php?action=query&list=allpages&format=json&apfrom="+txt.value+"&generator=alllinks&callback=func");
e.appendChild(o);
}
Appending "&prop=links" and/or "&generator=alllinks" to the URL doesn't seem to affect the result.
I would like to know what should I include in this portion:
'<a href="' + json.query.link+ '">'
in order to list the page titles with their respective links.
I have tried "json.query.allpages[i].pageID" and "json.query.alllinks" but it has not been working.
Edit:
Gave up on finding URL and went to do the pageid method instead.
Solved it with this:
e.innerHTML += i + ": " + '' + json.query.allpages[i].title + '' + "<br />";
You can create the link directly using the pageid:
function func(json) {
var e = document.getElementById('wiki');
var i;
for (i=0; i < json.query.allpages.length; i++) {
e.innerHTML += i + ": " + '' + json.query.allpages[i].title + '' + "<br />";
}
}
The fact that you have both list= and generator= in the same query suggests to me that you don't fully understand how generators work in the MediaWiki API.
Basically, a generator is a way to use a list as the source of pages to retrieve properties for. It does not make any sense to use a generator as the input to another list query. That is, you'd normally use generator= with prop=, not with list=. The only reason MediaWiki (seemingly) allows that at all is because:
You can make a query with a page list (or a generator) but no prop= parameter, like this. If you do, you'll just get a minimal default set of properties (title, namespace and page ID) for the pages.
You can also combine a properties query and a list query into a single request, like this. You'll just get the results for both queries, merged into the same JSON/XML/etc. output, but they'll be otherwise completely separate. (You can also make multiple simultaneous list queries that way.)
Thus, when you combine a generator= with a list= query, you'll get both the usual output for the list and a minimal set of properties for the pages matched by the generator. The two outputs will not be connected in any real way, except for being part of the same API response.
Anyway, you wanted to know how to obtain the titles and URLs of all Wikipedia pages with links. Well, as schudel notes in their answer, to get the URLs for some pages you need prop=info with inprop=url; to run this query on all linked pages, you can use generator=alllinks. Thus, you end up with:
https://en.wikipedia.org/w/api.php?action=query&prop=info&inprop=url&generator=alllinks
Note that this gives information about all pages that have links from them. To run the query on all pages with links to them, you need to add the parameter galunique=true:
https://en.wikipedia.org/w/api.php?action=query&prop=info&inprop=url&generator=alllinks&galunique=true
(Yes, this is documented, although not as clearly as it perhaps could be.)
Obviously, the link targets will include a lot of missing pages. The fact that the link sources seemingly also include a missing page with an empty title is presumably due to a faulty record in Wikipedia's link database. This could be fixed by rebuilding the (redundant) links table, but, given Wikipedia's size, this would take quite a bit of time (during which, presumably, the site would have to be locked into read-only mode to avoid further inconsistencies).
To process this data in JavaScript, you could do something like this:
var apiURL = 'https://en.wikipedia.org/w/api.php?format=json&action=query&prop=info&inprop=url&generator=alllinks&callback=myCallback';
function myCallback(json) {
var e = document.getElementById('wiki');
for (var id in json.query.pages) {
var page = json.query.pages[id];
if (typeof(page.missing) !== 'undefined') continue;
e.innerHTML +=
id + ': ' + escapeHTML(page.title) + '<br />';
}
// handle query continuations:
if (json.continue) {
var continueURL = apiURL;
for (var attr in json.continue) {
continueURL += '&' + attr + '=' + encodeURIComponent(json.continue[attr]);
}
doAjaxRequest(continueURL);
}
doAjaxRequest(apiURL + '&continue=');
Note that I've also included a basic mechanism for handling query continuations, since you'll surely need to handle those when using alllinks. Implementing the helper functions escapeHTML() and doAjaxRequest() is left as an exercise. Also note that I haven't actually tested this code; I think it's OK, but there might be bugs that I've missed. It will also produce a ridiculously long list, and probably slow your browser to a crawl, simply because Wikipedia has a lot of pages. For a real application, you'd probably want to introduce some kind of an on-demand loading scheme (e.g. only loading more results when the user scrolls down to the end of the current list).

Is there a way cleanly use hidden classes in javascript when you dont know what the properties will be?

I have a (GIS) project which displays large amounts of customer data (Thousands of records) to clients. Where nescessary/possible/required, we use server side pagination/filtering/data manipulation but there are cases where it is most efficient to send the data in JSON format to the client and let their browser do the filtering.
The amount of data is large, so we format it to save on bandwidth and parsing time - instead of individual objects, we send a structure that includes the attribute names first and then the values in a single flat array. On the client, we rebuild this into more traditional json objects before other processing occurs. eg:
{attrNames:["foo","bar"],values:[1,2,3,4,...]) -> [{foo:1,bar:2},{foo:3,bar:4},...]
The code for doing this looks a little like this:
function toObjectArray(attrNames, values){
var ret = [];
var index = 0;
var numAttrNames = attrNames.length;
var numValues = values.length;
while(index < numValues){
var obj = {};
for(var a = 0; a < numAttrNames; a++){
obj[attrNames[a]] = values[index++];
}
ret.push(obj);
}
return ret;
}
Given that the attributes may change depending on the customer data, is there a way to do this translation that takes advantage of hidden classes in modern javascript engines like V8? I have done some micro benchmarks similar to our use case ( http://jsfiddle.net/N6CrK/1/ ) where working with json such that hidden classes are used is orders of magnitude faster than building the objects as above. I can get some of this boost using "eval" to create objects, but this feels ugly (This is demonstrated in the js fiddle). Is there a better way? Perhaps using some variant of Object.create, or something like it?
You mean something like this right?
function toHiddenObjectArray(attrNames, attrValues){
var numAttrNames = attrNames.length,
numValues = attrValues.length;
function Data( values ) {
for(var v = 0; v < numAttrNames; v++) {
this[attrNames[v]] = values[v];
}
}
var ret=[];
for( var i=0; i<numValues ; i+=numAttrNames ) {
ret.push( new Data( attrValues.slice(i,i+numAttrNames) ) );
}
return ret;
}
You can check our the fiddle here: http://jsfiddle.net/B2Bfs/ (With some comparison code). It should use the same "Hidden Class" (i.e. Data). Not sure how much quicker it is though!
But, if you really want to make your code none blocking, why not load the page, then request the data via AJAX, then run all you code when you get a response.
I can get some of this boost using "eval" to create objects, but this feels ugly
There's a less ugly way using the Function constructor. Also, further optimisations can be done by immediately assigning the values to the properties, instead of initialising them with null and then again iterating through the attrs array like the adHoc does it. You'd just pass each of the rows you get in the response (array? string? byte-whatever?) as a parameter to the factory.
Also I've moved the creation of the factory function out of the create function, so that only one function will be instantiated (and optimized after enough calls to it).
A decent amount of the time in your test loop is spent on the getTotal, so I've optimised this in a similar manner. Not using getTotalAdHoc in testing the optimised solution drastically reduces the measured time (you can test with getTotalOptimum as well).
var factory = new Function("arr", "return{"+attrs.map(function(n, i){
return n+":arr["+i+"]";
}).join(",")+"};");
var getSum = new Function("o","return "+attrs.map(function(n, i){
return "o."+n;
}).join("+")+";");
(updated jsfiddle)
I haven't yet tried moving the complete loop into the generated code, which could avoid a few function calls, but I don't think this is necessary.
For some reason I just recalled this question... and I just came up with a solution that is way dirtier than using eval but which causes a huge speed boost. The downside of it is that code will be similarly little maintainable as when using eval.
The basic idea is: When receiving the attribute names, generate the function code to parse the following data in JavaScript and add it in a <script> tag to the <head>.
Yeah, isn't that dirty? :-)
If performance is so critical for you, it will definitely help you... here's a modified version of your microbenchmak that proves it: http://jsfiddle.net/N6CrK/17/
Some remarks on the code...
The two functions createWithGeneratedFunction and getTotalWithGeneratedFunction are simply wrapper functions that can be used by productive code. All they do is make sure that the <script> with the generated functions is set up and then call it.
function createWithGeneratedFunction(numValues){
makeSureScriptsAreSetUp()
return createWithGeneratedFunctionAdded(numValues);
}
function getTotalWithGeneratedFunction(objs){
makeSureScriptsAreSetUp()
return getTotalWithGeneratedFunctionAdded(objs);
}
The actual workhorse is the makeSureScriptsAreSetUp with the functions it creates. I'll go through it line by line:
function makeSureScriptsAreSetUp() {
if(scriptIsSetUp)
return;
If the required <script> tag was already set up this function will directly return since there is nothing to do for it anymore.
var head = document.getElementsByTagName('head')[0];
var script = document.createElement('script');
var theFunctions = "";
This prepares the creation of the required functions. The theFunctions variable will be filled with the code that is going to be put into the <script> tag content.
theFunctions =
"function createWithGeneratedFunctionAdded(numValues) {" +
" var ret = [];" +
" var value = 0;" +
" for(var i = numValues; i-- > 0;) {" +
" ret.push({";
for(var attr in attrs) {
theFunctions +=
" " + attrs[attr] + ": value++,";
}
theFunctions +=
" });" +
" }" +
" return ret;" +
"}" +
"";
This completes the code for the parsing function. Obviously it just "parses" the numbers 0 to numValues in this microbenchmark. But replacing value++ with something like TheObjectThatTheClientSentMe.values[value++] should bring you very close to what you outlined in your question. (Obviously it would make quite a lot of sense to rename value to index then.)
theFunctions +=
"function getTotalWithGeneratedFunctionAdded(objs) {" +
" var ret = 0;" +
" for(var i = objs.length; i-- > 0;) {" +
" var obj = objs[i];" +
" ret += 0";
for(var attr in attrs) {
theFunctions +=
" + obj." + attrs[attr];
}
theFunctions +=
" ;" +
" }" +
" return ret;" +
"}";
This completes the code for the processing function. Since you seem to require several processing functions, especially this code could become somewhat ugly to write and maintain.
script.text = theFunctions;
head.appendChild(script);
scriptIsSetUp = true;
}
In the very end we simply set the <script> tag content to the code we just created. By then adding that tag to the <head>, Chrome's hidden class magic will occur and will make the code VERY fast.
Concerning extensibility: If you have to query different attribute/value sets from the server on the same page, you might want to give each parsing/processing method set unique names. For example, if you first receive attrs = ["foo","bar"] and next attrs = ["foo","bar","baz"] you could concat the underscore-joined attribute name array to the generated function names.
For example, instead of using createWithGeneratedFunctionAdded you could use createWithGeneratedFunctionAdded_foo_bar for the first attribute/value set and createWithGeneratedFunctionAdded_foo_bar_baz for the second attribute/value set. An attr parameter could then be added to the wrapper functions that will be used to generate the correct code line for an eval (yes, here the evil eval would return) to trigger the correct generated function. Obviously, the attr parameter would also be required for the makeSureScriptsAreSetUp function.

Need to get an array of the names of all applicationScope variables

In an application I am working on I need to get a list of the names of all applicationScope variable then I need to cycle through them and filter out the ones starting with a know string say $xyx. I thought that the applicationScope.keySet().
I'm using this code for starter:
var col = applicationScope.keySet();
var itr:java.util.Iterator = col.iterator();
if (itr.hasNext()){
var str:String = itr.next();
dBar.info(str,"Value = ");
}
if I put the variable col in a viewScope it shows a list of all the keys. but when I run the script the values displayed in the dBar info are not the keys but some other information that I'm not sure where it comes from.
I should just be able to iterat through the list of keys, am I missing something?
This code is in the before page loads event
After some poking around and experimenting I got this to work:
var col = applicationScope.keySet();
var itr:java.util.Iterator = col.iterator();
while (itr.hasNext()){
var str:Map.Entry = itr.next();
if (str.substring(0,9) == "$wfsLock_"){
//do stuff
}
}
so I'm now a happy camper.
Although your code works in SSJS, it is not correct (and that's why I don't like SSJS...).
The applicationScope is an implementation of the java.util.Map interface and the keySet() method returns a Set containing the keys in that Map. Every entry is (probably) a String (other data types like integers are actually also valid). The line
var str:Map.Entry = itr.next();
doesn't cast it to a Map.Entry: it doesn't really do anything: str remains a string.
The Map interface also has an entrySet() method that returns the entries (Map.Entry). You can use that to retrieve the key as well as the value:
var it = applicationScope.entrySet().iterator();
while (it.hasNext()) {
var entry = it.next();
print( entry.getKey() + " = " + entry.getValue() );
}
(in this code the print() line will use the toString() method of the key as well as the value to send information to the console)
I see from your code that you've installed my XPages Debug Toolbar. You can also use that to quickly check what's in the scopes and what the actual datatype is.

Parsing malformed JSON with Javascript

I want to parse this content using Javascript. The data looks like this:
{"ss":[["Thu","7:00","Final",,"BAL","19","ATL","20",,,"56808",,"PRE4","2015"],["Thu","7:00","Final",,"NO","10","GB","38",,,"56809",,"PRE4","2015"]]}
Every single tutorial online teaches you how to parse JSON using Twitter, but I am not quite sure how parsing with JSON works.
I would like to set this up on a website to view the NFL team scores for a fun project and a good learning experience about parsing JSON, as I could care less about Twitter stuff.
Is this possible? Any good tutorials to start with? Even some starting code?
Generally speaking, you can use JSON.parse to do this. However, that snippet that you have does not appear to be strictly valid JSON (as seen here: http://jsfiddle.net/yK3Gf/ and also by validating the source JSON here: http://jsonlint.com/).
So you will either need to parse it by hand, or get nfl.com to fix up their JSON.
As an alternative, their JSON does parse successfully when using eval(), so you could parse it with something like:
var parsedData = eval('(' + jsonData + ')');
...as shown here: http://jsfiddle.net/yK3Gf/1/
Though be aware that parsing JSON in this way is generally frowned upon (particularly when the data being parsed is being delivered by a third-party source), as it leaves you open to XSS attacks should the data happen to include any executable code inside of it.
I am in a similar position - non javascript expert working on a fun project to familiarize myself with javascript, ajax, and json.
I took three different steps to handle the problem. I welcome any feedback on improving the solution.
The first step is to query the nfl site to pull down the scores. Because the source of the json, the nfl site, is different from your site, you will have to work around the javascript security constraints against cross domain querying. I found this stackoverflow link to be a good reference. I used JSONP for the workaround. I used http://whateverorigin.org/ as the indirection site.
$.getJSON('http://whateverorigin.org/get?url=' + encodeURIComponent('http://www.nfl.com/liveupdate/scorestrip/scorestrip.json') + '&callback=?', handleQueryForScoresResult);
As others have pointed out, the nfl site returns invalid json data. The following sample line illustrates the problem:
["Sun","4:25","Final",,"TEN","7","MIN","30",,,"55571",,"REG5","2012"],
Notice the empty array element values (the repeated commas with no data in between). So in my json callback function, I corrected the data by adding empty strings (two double quotes) to repeated commas before calling jquery to parse the json data:
function handleQueryForScoresResult(data) {
var jsonStr = data.contents;
jsonStr = jsonStr.replace(/,,/g, ',"",');
jsonStr = jsonStr.replace(/,,/g, ',"",');
var scoresData = jQuery.parseJSON(jsonStr).ss;
.
.
.
}
Lastly, I created GameScores object to encapsulate the json data.
function GameScore(scoreData) {
this.scoreData = scoreData;
scoreData[2] = scoreData[2].toLowerCase();
scoreData[5] = parseInt(scoreData[5]);
scoreData[7] = parseInt(scoreData[7]);
}
function GameScore_getAwayTeam() { return this.scoreData[4]; }
function GameScore_getHomeTeam() { return this.scoreData[6]; }
function GameScore_isFinal() { return this.scoreData[2]=="final"; }
function GameScore_getHomeTeamScore() { return this.scoreData[7]; }
function GameScore_getAwayTeamScore() { return this.scoreData[5]; }
function GameScore_doesHomeTeamLead() { return this.scoreData[7]> this.scoreData[5]; }
function GameScore_doesAwayTeamLead() { return this.scoreData[5]> this.scoreData[7]; }
function GameScore_getWeekId() { return this.scoreData[12]; }
GameScore.prototype.getHomeTeam = GameScore_getHomeTeam;
GameScore.prototype.getAwayTeam = GameScore_getAwayTeam;
GameScore.prototype.isFinal = GameScore_isFinal;
GameScore.prototype.getHomeTeamScore = GameScore_getHomeTeamScore;
GameScore.prototype.getAwayTeamScore = GameScore_getAwayTeamScore;
GameScore.prototype.doesHomeTeamLead = GameScore_doesHomeTeamLead;
GameScore.prototype.doesAwayTeamLead = GameScore_doesAwayTeamLead;
GameScore.prototype.getWeekId = GameScore_getWeekId;
I only added a few accessors as I did not need most of the data. Your needs may vary.
We are using mootools for stuff like that, but you can do it it plain JavaScript as well: http://www.json.org/js.html.
Let's assume you already have a valid JSON String (jsonString) to parse. (If you don't know how to retrieve a String to parse using XMLHttpRequest from the given url you will have to look into that first.)
With plain JavaScript you will have to add Douglas Crockford's JSON library (or something similar) in order to provide a parsing Function if there is no native implementation:
var json = json_parse(jsonString) ;
link
With a JavaScript library like jQuery this would be
var json = $.parseJSON(jsonString) ;
Now, traversing the resultant JSON Object is a whole other issue, because you will have to know its structure before you can retrieve specific data.
In this particular case -- if it was indeed well formed -- you would have to do the following:
var data = json.ss ;
for(var i = 0 ; i < data.length ; i++) {
var entry = data[i] ;
var day = entry[0] ; //!! the Arrays seem to have a format where the first entry always contains the data and so forth...
/* ... */
// then do something with the data bits
}
Your main problem is that fact that the JSON your pulling in is malformed or not valid according to RFC 4627.
What you can do is grab the copy the JSON data and format it using this tool http://www.freeformatter.com/json-formatter.html
After you have the formatted version then you can use the jQuery ajax call
$.ajax({
url: "your-formatted.json",
dataType: 'json',
success: function (data) {
for (var i = 0; i < data.ss.length; i++) {
document.write("Day: " + data.ss[i][0]);
document.write("<br/>");
document.write("Time: " + data.ss[i][1]);
document.write("<br/><br/>");
}
}
});
You shouldn't actually use document.write in your application. This is only for example purpose of displaying the data.
For this specific issue (the empty indexes within the arrays from the JSON response) I did a regex replacement with a lookahead assertion. Considering that request contains the XMLHttpRequest:
request.responseText.replace(/,(?=,)/gm, ",\"\"")
This will turn ,, into ,"", and will also work in case there are more commas in sequence, so ,,, becomes ,"","",. You can use JSON.parse() afterwards.
This malformed JSON can be parsed by the dirty-json NPM package (I am the author).
You can test a demo of the parser here: https://rmarcus.info/dirty-json
The parser interprets the JSON in your original question as equivalent to the following valid JSON:
{
"ss": [
[
"Thu",
"7:00",
"Final",
"BAL",
"19",
"ATL",
"20",
"56808",
"PRE4",
"2015"
],
[
"Thu",
"7:00",
"Final",
"NO",
"10",
"GB",
"38",
"56809",
"PRE4",
"2015"
]
]
}

Categories

Resources