jQuery - consuming JSON resources - some return data, others don't. Why?
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"></script>
<script type="text/javascript">
$(document).ready(function(){
htmlobj=$.ajax(
{url:"http://www.google.com/calendar/feeds/developer-calendar@google.com/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 c开发者_如何学JAVAan 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.
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.
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.
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
精彩评论