Sunday, February 08, 2009

Using jQuery with NYT JSON API

New York Times recently made public a great API that lets you search all of their articles from 1981 to present, and get the data back in JSON format.
I decided to use this API to add some relevant news stories to a site i have been working on. I was going to use jQuery to pull the data using $.getJSON() and shove it into some divs on my site.

Problem:
I quickly ran into a problem. NYT is retuning plain JSON, not JSONP. JSONP is needed to do cross-domain JSON calls. jQuery will make a jsonp call if you add the following to the request url:
jsoncallback=?
In the background, what happens is that jQuery replaces the ? with a function is creates, for example jsonp1229009. jQuery is expecting a response of:

but new york times is returning:

When jQuery pulls that response into a script tag, and executes in, i get the following error in firefox: "Invalid Label".

Solution:
What i needed was a JSONP wrapper. Luckly, i have a friend who knows perl =) I asked him to write a service that will take 2 params: url and callback. Where URL is an encoded URL i am requesting, and callback is the param to wrap the response in. It worked out nicely, i can now use ANY JSON API and get JSONP back. This is the perl source:



Here is my crude and incomplete jQuery plugin that gets me a couple of articles with predefined fields and displays them on my site:



i call it like this:

13 comments:

  1. Funny...I was looking into it on the weekend and could not solve it. I will try to use the perl code and convert it into ruby since I am using ruby.

    ReplyDelete
  2. @andhapp:
    mind posting your ruby code here, or a link to it, or something, when you get it working?

    ReplyDelete
  3. Why not just put a straight pass-thru proxy on the site that serves your web page so you can use the JSON directly?

    ReplyDelete
  4. @anon:
    i didnt make a pass through because i didnt want to restrict myself to using this on that one host, i wanted to be able to use this proxy on many sites, some of which might be simple html/js only type sites

    ReplyDelete
  5. A lot of people use Google AppEngine to turn JSON into JSONP

    ReplyDelete
  6. I see, i tried using yahoo pipes before i did this, but it was too hard to figure it out vs a bit of perl. Since i dont know python the app engine isnt a choice either. On the other hand, when they open the java API, ill be getting an account.

    ReplyDelete
  7. Great article, the whole cross-domain jsonp is confusing to me. It seems like a lot of people use json with their apis from other API's - do most use server side programming to get around the issue?

    ReplyDelete
  8. @Jake:
    There is no way to use json that does not originate from your own domain in you javascript, so yes, if this is the case, you have to write server side code to do a HTTP GET on the json URI.

    ReplyDelete
  9. Its just the article i was searching for.
    Ive been having the same problem man.
    The url
    http://twittercounter.com/api/?username=Anand_Dasgupta&output=json&results=3&callback=status
    sends back only the json array but without the callback and its really frustrating
    If you have the php version of this code could you provide the link.
    Any help will be appreciated.

    ReplyDelete
  10. @anand:

    sorry man, i dont have the php version of the above perl code. Good luck getting it working. if you have good results, post a link here to help others =)

    ReplyDelete
  11. I've made a jsonpwrapper.com. It's written in Ruby and available on GitHub.

    ReplyDelete
  12. Check out my article on Server-Side proxies to get basic versions of a proxy in your implementation language of choice (PHP, Python, Perl, Java, C#, etc):

    http://bcmoney-mobiletv.com/blog/2009/05/01/the-server-side-proxy/

    Please feel free to post updates in the comments section, when I feel like they are good enough (and have satisfactory validation/parameter checking), then I'll drop them all on GitHub.

    ReplyDelete
  13. I think it's worth noting to new visitors of this page that most of the NYT APIs now support JSONP.
    You need to change the extension to .jsonp and add the callback function name in the query string; however for some odd reason they don't mention it in the API descriptions.

    http://api.nytimes.com/svc/books/v2/lists/hardcover-fiction.jsonp?callback=foo&api-key= http://api.nytimes.com/svc/events/v2/listings.jsonp?callback=foo&query=jazz&api-key=

    ReplyDelete