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.





October 6th, 2006 at 7:24 pm
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.
November 22nd, 2006 at 4:42 pm
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?
November 23rd, 2006 at 4:24 pm
Sorry jp, I was a little over-concise. You’ll also want to respond to html:
November 24th, 2006 at 6:53 pm
[…] Tim Lucas wrote a great article introducing a render_json method to add to your base ApplicationController. […]
December 2nd, 2006 at 2:26 am
[…] SitePoint Blogs » JSON-P output with Rails Wow. I like their code blocks, too. Neato. (tags: json rubyonrails rails jsonp Programming webdesign) […]
December 25th, 2006 at 4:20 am
so what about PUT and POST?
December 29th, 2006 at 10:48 am
yeah: what do you mean? There’s nothing GET specific about this. It’ll work just fine for PUT and POST too.
March 8th, 2007 at 11:14 pm
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
March 9th, 2007 at 7:25 am
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.
March 13th, 2007 at 11:50 pm
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.
March 18th, 2008 at 10:10 pm
Can you show a cross browser JSON post example?
April 29th, 2008 at 1:52 am
[…] 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中文社区翻译团队 […]