Blog Post RSS ?

Blogs » Ruby on Rails » JSON-P output with Rails
 

JSON-P output with Rails

by Tim Lucas

At the recent Web Directions 06 conference Cameron Adams and Sitepoint’s own Kevin Yank gave a talk on Mashups and APIs, with a mention of JSON-P.

JSON-P is a method of wrapping the JSON output of your API calls to allow other developers to call your API from within their page, bypassing the browser security mechanism.

If you peek at the HTML source of Web Connections you’ll notice we’re using JSON-P internally to provide the JS data to do the mapping. In the URL of the JSON-P call we can specify the parameter variable, callback or both, and this will allow others to use our JSON in their own mashups.

It also integrates nicely with the new Rails REST functionality. For example, Jeremy Keith’s profile page can also be output in JSON format by plugging ‘.js’ on the end. This is nice, but not very useful if you wanted to call it from another page.

Say Jeremy wanted to mashup this data on his own website to show who he’s friends with. He’d need some kind of JSON-P output so he can access the data from a script tag.

To add the JSON-P “padding” it’s just a matter of specifying a the “variable” parameter declaring the name of the Javascript variable you want the output assigned to. For this example we’ll specify ‘variable=personJSON’. Notice the difference in output? Now try specifying callback, or both callback and variable.

So how is this implemented behind the scenes? I have a helper function which I use throughout my application to output JSON:


class ApplicationController < ActionController::Base
  protected
    def render_json(json, options={})
      callback, variable = params[:callback], params[:variable]
      response = begin
        if callback && variable
          "var #{variable} = #{json};\n#{callback}(#{variable});"
        elsif variable
          "var #{variable} = #{json};"
        elsif callback
          "#{callback}(#{json});"
        else
          json
        end
      end
      render({:content_type => :js, :text => response}.merge(options))
    end
end

I can then use this in my PeopleController#show action quite simply:


class PeopleController < ApplicationController
  def show
    @person = Person.find(params[:id])
    respond_to do |format|
      format.js { render_json @person.to_json }
    end
  end
end

and that’s all there is to it. JSON-P output with Rails.

This post has 12 responses so far

  1. As we noted in our presentation, be aware of the security implications of JSON-P before you use an API of this type. If you don’t trust the provider of the API, you shouldn’t use JSON-P.

    Specifically, the site providing the API is able to send any JavaScript code it likes, including code that can compromise your site’s security.

     
  2. so, with the above additions you get the dual functionality of returned json-p when accessing /show/1.js? versus html with /show/1 ?

    I am only ever able to get a json reponse with /show/1

    Am I missing something that allows for the retrieval of html vs json by using a file extension?

      def show
        @grocery = Grocery.find(params[:id])
       
        respond_to do |format|
            format.js { render_json @grocery.to_json }
           #format.js { render({:content_type => :js, :text =>  @grocery.to_json})}  
        end
      end
     
  3. Sorry jp, I was a little over-concise. You’ll also want to respond to html:

    
     def show
        @grocery = Grocery.find(params[:id])
    	
        respond_to do |format|
            format.html # falls back on the rhtml file
            format.js { render_json @grocery.to_json }
        end
      end
    
     
  4. […] Tim Lucas wrote a great article introducing a render_json method to add to your base ApplicationController. […]

     
  5. […] SitePoint Blogs » JSON-P output with Rails Wow. I like their code blocks, too. Neato. (tags: json rubyonrails rails jsonp Programming webdesign) […]

     
  6. so what about PUT and POST?

     
  7. yeah: what do you mean? There’s nothing GET specific about this. It’ll work just fine for PUT and POST too.

     
  8. Strictly speaking, this isn’t really the “JSONP” protocol AFAICT, but an application of the principle behind JSONP. That is, don’t just return JSON, but instead let the caller tell the server how to augment the JSON.

    JSONP is a simple protocol where there’s a single relevant parameter in the URL, called precisely “jsonp”. The idea is to be as general as possible. Using JSONP, it is possible to specify a callback or a variable or anything else you could imagine (e.g. you could pass in “jsonp” param as “el.style.backgroundColor=” to affect an element’s appearance).

    http://ajaxian.com/archives/jsonp-json-with-padding

     
  9. Michael: thanks for clearing that up. What’s being used as the definitive document describing JSONP “protocol”? Bob Ippolito’s blog post it? It’s definitely sensible to reduce it all down to one parameter and keep it consistent between services. I like the idea of keeping it generic, and calling it “jsonp”, though I think the concept of a “callback” parameter (as is used by a fair few APIs now) is somewhat more intuitive than a generic “jsonp” parameter.

     
  10. Tim, yes Bob’s original post is the closest thing to a definitive reference I know of. Maybe it could do with an RFC just to give it some more momentum and cred with the enterprise.

    Agree, “callback” works too and is arguably better as it is just as general and intuitive. Downside is it can’t be inlined as an anonymous function, so it may entail a bit more JS code than some JSONP usages, which may make people want “variable” too, which starts to get complex and error-prone for API providers, which is the argument for JSONP :). If I were implementing an API, I would probably provide all three, as they can happily co-exist.

     
  11. Can you show a cross browser JSON post example?

     
  12. […] with Rails 9f/^m.PD+i:ITl.pD0 原文作者:Tim Lucas ‘`/Sn@|T0 原文地址:http://www.sitepoint.com/blogs/2 … -output-with-rails/ My0qI]0 Ruby Community:S mYM_6|1wa 译者:Ragnarok@Ruby中文社区翻译团队 […]

     

Sponsored Links

Leave a response

You are not logged in, log in with your SitePoint Forum username and password.

-OR- Post Anonymously

* Make sure any code samples are escaped (i.e. ‘<b>’ becomes ‘&lt;b&gt;’).

If not logged in, your comments will be placed in a moderation queue. This means your comment may not appear until one of our moderators approves it.

SitePoint Marketplace

Buy and sell Websites, templates, domain names, hosting, graphics and more.