Be careful with returnFormat and JSON

This post is more than 2 years old.

A user pinged me earlier this morning with an interesting issue. His Ajax application wasn't working as expected. He was using jQuery to hit a CFC. Instead of showing you his code, I simplified it a bit which should make the problem a bit simpler to see. Try and figure it out before reading on:

<cffunction name="getTime2" access="remote" returnFormat="json"> <cfset var s = {}> <cfset s.time = now()> <cfset s.name = "Current Time"> <cfreturn serializeJSON(s)> </cffunction>

It's a bit subtle - but the issue is that he mixes both returnFormat and serializeJSON. I've blogged about returnFormat quite a bit. It's one of my favorite features of ColdFusion 8 and it got little press. His use of it here though is not something I normally recommend. You can pass returnFormat as an argument in the request or you can specify it in the method inline as he did. To me - using it inline is a bad idea. Not "bad" bad, but I don't think the CFC should be concerned with its return form. Instead, it should simply handle it's business logic and let the caller ask for a particular format.

Where things go wrong is the serializeJSON. What's happening here is that CF first runs the code of the method (Make a struct, then JSON it), and then it formats the result in JSON. So basically it JSON encodes a string that is already JSON encoded.

If you view this result (*), you can see the result is a bit funky:

"{"TIME":"June, 03 2008 08:20:06","NAME":"Current Time"}"

All those \ should tip you off. If you remove the serializeJSON, you see a result that should look a bit better:

{"TIME":"June, 03 2008 08:20:06","NAME":"Current Time"}

I'd remove both the serializeJSON and the returnFormat. I'd then edit the jQuery code's URL to add returnFormat=JSON.

*Ok, so let me use this blog entry to say once again that 99% of Ajax problems can be solved with a tool like Firebug. Firebug would have let you see the Ajax request and response, and if you were familiar with JSON, it would have been an big clue. It's also a handy way to see times when you forget to turn off CF debugging.

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 6/3/2008 at 5:35 PM

Thumbs up for FireBug. I don't think I could even build AJAX applications without it. It simply makes work possible.

Comment 2 by Sam Farmer posted on 6/3/2008 at 6:10 PM

Ditto. I find the Javascript cfdebug pretty helpful as well.

Comment 3 by Jane Carter posted on 6/6/2008 at 9:21 AM

Thanks for the article: it's saved us a lot of hassle.

By the way, please note that "its" is spelled wrongly in the sentence "with it's return form". "it's" means "it is" or "it has", not "of it".

Comment 4 by Raymond Camden posted on 6/6/2008 at 3:31 PM

Believe it or not - I have a degree in English. ;) Fixed. I also changed considered to concerned.

Comment 5 by ike posted on 6/7/2008 at 6:55 AM

I was talking about that with some folks on Tribe recently actually... about how it feels like I'm constantly noticing other people substituting homonyms or just plain not the word they intended when they're writing up blogs or forum posts. Of course, if you noticed yourself doing it at the time, you would correct yourself before it went out, so it's something that only someone else can notice. Although yourself at a later time also qualifies as someone else. :P I was assured that yes indeed, I do it too.

Comment 6 by Raul Riera posted on 6/8/2008 at 1:36 PM

When you dont specify the serializeJSON, how do you tell the function to return the JSON as a column query format. Like this

returnFormat=json&queryFormat=column

I use that when I want to "tell the CFC to do it via an URL" but how can I do the same thing directly on the CFC file?

<cffunction name="foo" returnFormat="json" queryFormat="column">

Is not good :(

Comment 7 by Raymond Camden posted on 6/8/2008 at 7:05 PM

Rual - why would want to? If you want a CFC to always (or by default) return the json, then do it in CFML, use the serializeJSON with the right arg for queryformat. But again though I wouldn't do that. Keep the CFC generic and use the URL params.

Comment 8 by Raul Riera posted on 6/8/2008 at 10:28 PM

Yeah, in fact I have it that way, but I have been playing around with Railo and it appears it doesnt support the URL thing. And when trying to do it via CFML I dont get the same result as CF8

This is a Spry JSONDataset.

Comment 9 by Raymond Camden posted on 6/8/2008 at 11:41 PM

If we didn't have the url thing, then I'd do it in the CFC I guess, but I'd build _another_ method. Ie, one core getFoo() method that returns a native CF query, or whatever, and another method for ajax that wraps getFoo(). That's what I'd do in Railo.

Comment 10 by Stefan Vesterlund posted on 7/3/2008 at 3:47 PM

I was wondering - is there no way to set the returnformat programatically inside the function?

if (req is JSONP)
arguments.returnformat='json'
else
arguments.returnformat='wddx'

It feels a bit weird that you can send it as an argument but not treat it as one.

Comment 11 by Raymond Camden posted on 7/3/2008 at 4:04 PM

Well, you could obviously do this yourself. Use returnformat=plain and then return wddx or json. To me, I don't view returnFormat as an argument, but more as a operator on the function. (But I haven't had my coffee yet so what do I know?)

Comment 12 by Stefan Vesterlund posted on 7/3/2008 at 4:11 PM

Ahh... I found it, after a bit more trial and error :)

if (code executed indicates json return)
url.returnFormat="JSON";
else
url.returnFormat="plain";

That will make my life easier. Sometimes it is simply easier to decide on the server what the returnformat should be, but only after you see the request and it's result. For instance if you have the same methods being accessed by both JSONRPC and JSONP.

Comment 13 by Raymond Camden posted on 7/3/2008 at 4:16 PM

Heh, that's cheating. That actually works though? I'll do a test here and blog it later today if so (unless you want to blog it). I don't like it - but it's interesting.

Comment 14 by Stefan Vesterlund posted on 7/3/2008 at 4:23 PM

Cheating on a computer does not really count as a crime :)
Blog it if you wish, I have no blog. But it works for sure.

Comment 15 by Raymond Camden posted on 7/3/2008 at 5:24 PM

Blogged:

http://www.coldfusionjedi.c...

Thanks for sharing this Stefan.