Writing a JSONP service in ColdFusion

This post is more than 2 years old.

Earlier this week I blogged on JSONP (What in the heck is JSONP and why would you use it?). If that terms means nothing to you, be sure to read that article first. I thought it might be useful to talk about how you could write a ColdFusion API to support JSONP (as a producer I mean, for other people to use your API).

As we know (or hopefully now!), ColdFusion 8 made it very easy to serve JSON via Ajax. Consider the following method:

<cffunction name="getPerson" access="public" returnType="struct" output="false"> <cfset var s = {}> <cfset s.name = "Raymond"> <cfset s.age = "35"> <cfset s.suaveness = randRange(50,150)> <cfreturn s> </cffunction>

If I wanted to expose that structure in JSON, all I'd need to do is change access to remote and specify JSON in the URL. I'd request it like so:


The returnFormat there simply asks ColdFusion to convert the structure to JSON before sending it back to the client.

Ok, so what about JSONP? JSONP stands for JSON with Padding and that presents a problem to us. We can't just return a JSON string, we have to return a JSON string plus the padding, which is a function call. ColdFusion does support a "Don't do squat with my result, just return it" version - you just change returnFormat to plain. So given that, here is how I'd build support for JSONP:

<cfcomponent output="false">

<cffunction name="getPerson" access="public" returnType="struct" output="false"> <cfset var s = {}> <cfset s.name = "Raymond"> <cfset s.age = "35"> <cfset s.suaveness = randRange(50,150)> <cfreturn s> </cffunction>

<cffunction name="remoteGetPerson" access="remote" returnType="any" returnFormat="plain" output="false"> <cfargument name="callback" type="string" required="false"> <cfset var data = getPerson()>

&lt;!--- serialize ---&gt;
&lt;cfset data = serializeJSON(data)&gt;

&lt;!--- wrap ---&gt;
&lt;cfif structKeyExists(arguments, "callback")&gt;
	&lt;cfset data = arguments.callback & "(" & data & ")"&gt;

&lt;cfreturn data&gt;



I've added a new method here, remoteGetPerson. Normally this would call an application scoped CFC, but in this case my method resides in the same file. I serialize the data and then - optionally - wrap it with the callback. Arguments.callback is expected to be a function named defined in your client side code.

Notice that I hard coded the returnFormat. In the past I've recommended against that. I've said that the caller should request a format and the CFC method should be neutral - but in this case we are specifically building in support for JSON or JSONP. I made the padding optional - well - for no good reason I guess. I noticed Yahoo supports JSONP in their requests, but allows the callback function to be optional. Since JSON is just string data, it will work fine with returnFormat=plain.

So to test this, I wrote the following incredibly interesting demo:


<head> <script src="/jquery/jquery.js"></script> <script>

function runTest() { var surl = 'http://www.raymondcamden.com/demos/jsonp/test.cfc?method=remoteGetPerson&callback=?' $.getJSON(surl, function(data) { var res = 'Name: '+data.NAME+'<br/>' res += 'Age: '+data.AGE+'<br/>' res += 'Suaveness: '+data.SUAVENESS if(data.SUAVENESS > 100) res+=' (Rico-worthy)' res+='<br/>' $("#result").html(res) }) }

$(document).ready(function() { $("#testBtn").click(runTest) });

</script> </head>

<body> <input type="button" value="Test" id="testBtn"> <div id="result"></div> </body> </html>

This is a simpler version of what I wrote for InsideRIA. I've added a simple button that, when clicked, runs a call to my CFC method. Now obviously this is in the same domain so JSONP is overkill, but in theory, folks could download the code (fix the jQuery reference - yes - I know I need to switch to Google CDN!) and still be able to run it.

Two quick notes:

  1. I used jQuery in the example above, but you could use any other framework of your choosing. As long as you use jQuery. Kidding. (Not really.)

  2. Using Firebug to test? (Of course you are!) I was surprised to find that these Ajax requests do not show up under XHR. I had forgotten that JSONP works by injecting script blocks into your page. Just switch to Net/All or Net/HTML and you can see the requests.

Raymond Camden's Picture

About Raymond Camden

Raymond is a senior developer evangelist for Adobe. He focuses on document services, JavaScript, and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA https://www.raymondcamden.com

Archived Comments

Comment 1 by Ben Nadel posted on 3/11/2009 at 10:26 PM

It would be cool if you could use OnMissingMethod() in remote calls. Then, you could have a CFC decorate the target CFC and wrap its returns in the callback method. Something like:

data = target[ missingMethodName ]( missingMethodArguments )

return( callback & "(" & data & ")" );

Obviously, that syntax is not proper, but it would be a cool idea... but not possible.

Comment 2 by Shiva posted on 4/30/2009 at 9:34 AM

Very nice code. I really like to work with this but my problem is i am not able to run this in my local. In the firebug it says syntax error. I am using CF8 and i am a new be...

var surl = 'http://www.coldfusionjedi.c...

when i used the above surl it is working but when i use
var surl = 'test.cfc?method=remoteGetPerson&callback=?'

as my cfc is in the same folder as cfm file. why it is going wrong for me? Please help me.

Comment 3 by Raymond Camden posted on 4/30/2009 at 2:47 PM

Any more details on the syntax error? Line #? What happens if you specify a full url for surl, ie, http://localhost/etc.

Comment 4 by John Stuart posted on 8/31/2010 at 12:12 AM

Thank you, Raymond! I've been looking all day for this -- a clear set of code that addressed what was needed on both sides of the HTML/CF implementation of JSONP AJAX style calls. Everyone has missed big chunks of how it actually works and inserted obscuring frills that just seem to hide what was really going on. Thanks again for a clear explanation and code that actually worked when I copied and ran it. Rarer than you'd think.

Comment 5 by Raymond Camden posted on 8/31/2010 at 12:14 AM

No problem. Glad to help.

Comment 6 by Jason McNeill posted on 9/17/2012 at 11:04 PM

@Raymond: The link in the first sentence of the first paragraph of your article is no longer live. Looks like they have archived your posts. I found the link to the archived article:

Comment 7 by Raymond Camden posted on 9/17/2012 at 11:04 PM

Thanks - will edit the post.

Comment 8 by markw707 posted on 1/17/2014 at 4:31 AM

Very, very, very cool. It works like a dream.

Comment 9 by Gavin posted on 3/12/2014 at 8:05 AM

Another good post Ray.

Just noticed, The link to http://www.developria.com/2... is redirecting to http://www.adobe.com/devnet... now, I was wondering if you happened to have a copy of that post anywhere else?
If not for me, but for others trying to figure out what the heck jsonp is too.


Comment 10 by Raymond Camden posted on 3/12/2014 at 8:07 AM

See: http://www.raymondcamden.co...

I'll republish that post - it was a good one. (I'll probably forget to mention it here, so just check the blog. Daily. Hourly! ;)

Comment 11 by Raymond Camden posted on 3/12/2014 at 6:22 PM