JSON-P output with Rails

Share this article

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.

Tim LucasTim Lucas
View Author
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week