views:

370

answers:

3

I'm trying to figure out how to consume json URLs in the browser and render the data in my web pages using DOM. I am not getting a consistent or predictable response.

I found a JSON URL at Google Calendar which shows the json response in my browser if I just type the URL in the address bar.

I found another JSON URL at business.gov which shows a different json response in my browser if I just type the URL in the address bar. .

I then tried to use jQuery to issue $.ajax calls to consume and display both of these JSON resources.

<head>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.4.2.min.js"&gt;&lt;/script&gt;
<script type="text/javascript">
$(document).ready(function(){
  htmlobj=$.ajax(
            {url:"http://www.google.com/calendar/feeds/[email protected]/public/full?alt=json",
             async:false} 
            );

  if (jQuery.isEmptyObject(htmlobj.responseText)===true) {
    alert("htmlobj.responseText is empty");
  } else {
    alert("htmlobj.responseText has stuff in it");
  }

  $("#myDiv").html(htmlobj.responseText).fadeIn();

  htmlobj1=$.ajax(
         {url:"http://api.business.gov/geodata/city_county_links_for_state_of/CA.json",
                async:false, 
                dataType:'text', 
                });

  if (jQuery.isEmptyObject(htmlobj1.responseText)===true) {
    alert("htmlobj1.responseText is empty");
  } else {
    alert("htmlobj1.responseText has stuff in it");
  }

  $("#myGovDiv").html(htmlobj1.responseText).fadeIn();
});
</script>
</head>
<body>
   <h3>Google Calendar - json only</h3>
   <div id="myDiv" style="display:none"></div>

   <h3>Business.Gov</h3>
   <div id="myGovDiv" style="display:none"></div>
</body>

The Google Calendar JSON resource was consumed fine, but the business.gov JSON resource did not even come back in the response. (I checked with Firebug, and it returned HTTP code 200 with nothing in the response text).

How is it that both JSON URLs returned good JSON data in the browser, but only the Google Calendar URL could be consumed by jQuery.ajax while the business.gov URL could not be consumed by jQUery.ajax?

EDIT - June 19, 2010, 6:36 EST - Thanks @Juan Manuel and @TheJuice. I tried jsonp...here is what I got.

If I change the call to the following, I am able to get the browser to stop blocking the response from api.business.gov, but I can't get at the data (e.g. htmlobj2 is a nil)

  htmlobj2=$.ajax(
        {url:"http://api.business.gov/geodata/city_county_links_for_state_of/CA.json",
         async: false,
         dataType: 'jsonp',
         success: function(data, textStatus) {
            alert("Success");
            $('#myDiv').html("Your data: " );
       },
         error: function ( XMLHttpRequest, textStatus, errorThrown){
                    alert('error');
                }
    }
);

Whether I use dataType of 'jsonp' or 'script', I get the same result. htmlobj2 is nil, but the response header has the entire json data string. Furthermore, if I try to bind a callback function to the .ajax call with "data" as a parameter, that "data" parameter is also a nil object. Furthermore, neither the success or failure handler gets called.

How can I extract this JSON data from the response string and present it on my web page?

EDIT - June 22, 2010, 11:17 AM

I found a Ruby script and tweaked it to try and consume the URLs. I ran it in interactive Ruby (irb).

require 'rubygems'
require 'json'
require 'net/http'

url = "http://api.business.gov/geodata/city_county_links_for_state_of/CA.json"
resp = Net::HTTP.get_response(URI.parse(url))
data = resp.body
result = JSON.parse(data)
result.each{|entry| p entry["name"] + "," + entry["full_county_name"] }

I was able to use a similar Ruby script to consume the Google Calendar URL as well.

Bottom line? I was able to consume both JSON resources (api.business.gov and Google Calendar) using Ruby, but only the Google Calendar resource using Javascript/jQuery in my browser.

I'd appreciate any insight I can get. It doesn't seem clear from any of the documentation on the web or the API descriptions why the Google Calendar feed works in the browser no matter what, but the api.business.gov feed does not work in the browser using JSON or JSONP.

+2  A: 

It may be a problem with same origin policy

Can you try using JSONP?
I had the same problem (firebug showing empty data) and solved it with it, but I had control over the web service and could modify it to support it.

Juan Manuel
@Juan Manuel - I don't have any control over the web service at business.gov.
Jay Godse
@Juan Manuel - If that is the case, why did it work with the Google API, but not with business.gov. I used the same code.
Jay Godse
+4  A: 

As Juan Manuel pointed out, this is your browser protecting you from cross site scripting. If you take a look at your requests in Fiddler, you can see what is going on.

This is part of the response header from google:

HTTP/1.1 200 OK
Content-Type: application/json; charset=UTF-8
Access-Control-Allow-Origin: *
Rest Omitted...

This is from business.gov:

HTTP/1.1 200 OK
Date: Fri, 18 Jun 2010 21:52:10 GMT
Server: Mongrel 1.1.4
Status: 200 OK
X-Runtime: 0.36775
ETag: "172ec84fa79f748265e96d467af3d3dd"
Cache-Control: private, max-age=0, must-revalidate
Content-Type: application/json; charset=utf-8
Via: 1.1 api.business.gov
Content-Length: 229427
Proxy-Connection: Keep-Alive
Connection: Keep-Alive
Set-Cookie: .....7c5; path=/
Age: 0

[
  {"name": "Adelanto" ,
   "fips_county_cd": "71" ,
   "feat_class": "Populated Place" ,
   "county_name": "San Bernardino" ,
   "primary_latitude": "34.58" ,
   "state_name": "California" ,
..... (rest omited)

You see that your response from business.gov is actually returned, but blocked by the browser.

Update for your updates: The Google web service is handling the JSONP for you along with jQuery. The business.gov web service does not support JSONP apparently. You will need to use Ruby (server side code) to act as a proxy and consume the business.gov service then return the response to the client.

TheJuice
What is Fiddler?
Jay Godse
@Jay Godse - Fiddler is a windows app that acts as a proxy and allows you to see all HTTP traffic going in and out of your computer. It also allows you to modify that traffic. http://fiddler2.com
Rob Allen
+1  A: 

One difference between the two is the Content-Type the server is reporting for the results:

Fiddler is showing the Google Calendar call being returned as Content-Type: text/plain; charset=UTF-8 whereas business.gov is not specifying a Content-Type. application/json; charset=utf-8 (edited, my initial answer was from a Cached response).

The Content-Type essentially tells the browser what filetype the response is--it's fairly similar to a file-extension in Windows. It's also known as a MIME-Type and has some fairly far-reaching effects (for example, it takes precedence over the DTD in a HTML/XHTML file--so if you are serving XHTML with a text/html Content-Type then the browser will actually treat the response as HTML--so lots of sites that claim they are XHTML compliant are actually serving invalid HTML.


TheJuice seems to have seen different results in Fiddler, so for the sake of comparison here's the headers I saw in testing:

Google Calendar

HTTP/1.1 200 OK
Content-Type: text/plain; charset=UTF-8
Expires: Tue, 22 Jun 2010 15:25:41 GMT
Date: Tue, 22 Jun 2010 15:25:41 GMT
Cache-Control: private, max-age=0, must-revalidate, no-transform
Vary: Accept, X-GData-Authorization, GData-Version
GData-Version: 1.0
Last-Modified: Tue, 22 Jun 2010 12:19:15 GMT
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
Server: GSE
Content-Length: 49803

Business.gov:

HTTP/1.1 200 OK
Date: Tue, 22 Jun 2010 15:34:33 GMT
Server: Mongrel 1.1.4
Status: 200 OK
X-Runtime: 0.37833
ETag: "172ec84fa79f748265e96d467af3d3dd"
Cache-Control: private, max-age=0, must-revalidate
Content-Type: application/json; charset=utf-8
Content-Length: 229427
Via: 1.1 api.business.gov
Keep-Alive: timeout=15, max=100
Connection: Keep-Alive
STW
Thanks. That casts some insight on the problem. So...what must I do to the jQuery $.ajax call to ensure that I can read the response just like the Google Calendar response?
Jay Godse
Unfortunately I'm relatively new to jQuery and haven't ran into this--however, Fiddler (an HTTP proxy) will let you intercept and modify the response, so you could try changing the Content-Type header from business.gov to match Google's and see if it has an impact. Fiddler is available from www.fiddler2.com
STW