Returning NULL Values In JSON Using SerializeJSON() And ColdFusion

Posted April 5, 2011 at 9:29 AM by Ben Nadel

Tags: ColdFusion

As I've been setting up a JSON-RPC (Remote Procedure Call) API for a ColdFusion project, I've been learning a few little tips and trips about JSON formation. Last week, I talked about how struct keys defined using array-notation maintain case during serialization. This week, in accordance with the JSON-RPC spec, I learned that you can return NULL JSON values by storing NULL ColdFusion values.

To demonstrate, I've mocked up an incomplete JSON-RPC example. According to the JSON-RPC specifications, a properly formed response cannot contain both an Error and a Result value at the same time; one of them must always be null. In order to ensure that a true JSON-null is returned, you have to store a null value in your ColdFusion response struct.

  • <!---
  • Define our basic JSON-RPC response structure. Note that we
  • are using array-notation in order to maintain case in the
  • serialization process.
  • --->
  • <cfset response = {} />
  • <cfset response[ "jsonrpc" ] = 2.0 />
  • <cfset response[ "result" ] = "Blam!" />
  • <cfset response[ "error" ] = {} />
  •  
  •  
  • <!---
  • For JSON-RPC, we cannot return both a RESULT and an ERROR in
  • same response. One of them has to be null. In order to return a
  • null value in the a JSON-serialization, we need to actually store
  • a NULL value in the ColdFusion struct.
  • --->
  • <cfset response.error = javaCast( "null", "" ) />
  •  
  •  
  • <!--- Serialize the JSON-RPC response. --->
  • <cfset serializedResponse = serializeJSON( response ) />
  •  
  • <!---
  • Stream the JSON response back to the client.
  •  
  • NOTE: The Mime-Type that we are using here is plain text only for
  • debugging purposes. In a real-world situation, you'd be returning
  • the JSON as application/json.
  • --->
  • <cfcontent
  • type="text/plain"
  • variable="#toBinary( toBase64( serializedResponse ) )#"
  • />

As you can see above, we are using javaCast() to store our null ColdFusion value. Doing so essentially destroys the usability of the key from a ColdFusion standpoint; but, from a JSON serialization standpoint, it's just what the doctor ordered. Running the above code gives us the following JSON response:

{ "jsonrpc":2.0, "error":null, "result":"Blam!" }

As you can see, the "error" key contains a true null value.

While this isn't the point of the post in any way, I should also mentioned that if you use ColdFusion to deserialize a JSON string that contains a null value, ColdFusion converts it into the string, "null". As such, if you're setting up a JSON-RPC API, you'll probably end up having to use a combination of structKeyExists() and (neq "null") statements.

Going from a typeless, case-insensitive language like ColdFusion to a format like JSON can prove to be a bit tricky at times; but, other than a few irksome numeric-conversions, ColdFusion tends to handle it surprisingly well - as long as you know how to work the system.




Reader Comments

Apr 5, 2011 at 10:49 AM // reply »
54 Comments

I have a strong emotional response to JSON-RPC. We internally have a server API that requires requests made in JSON and returns JSON responses. Getting back JSON responses is quite normal, and many interfaces implement this without calling themselves 'JSON-RPC'.

The significant issue is making requests in JSON. You must serialize the request with JSON.stringify (not avaiable in <IE8) and is not backwards compatible with HTML forms. If you are using jQuery, it will try to URLEncode your JSON object and seems to like to do the same to stringified JSON, so I also have to set processData false. I've ended up making a whole API to handle all of this in order to make even basic requests to the server.

So I beg you, change the name!


Apr 5, 2011 at 10:56 AM // reply »
11,314 Comments

@Drew,

For this project we're actually integrating with a 3rd party system that will be posting to our API. I am not even sure if JSON-RPC is easily doable with an AJAX-style approach. You can probably manually finagle the way data is sent; but in our case, the JSON value actually has to be posted as the request body (ie. getHTTPRequestData().content).

Honestly, I'm not crazy about the JSON-RPC specs; as you are saying, there's all kinds of complications when it comes to dealing with the browser. I'm only using it because it's pre-established in our integration spec.

At the end of the day, I'd rather just supply a standard URL interaction and then just have a normalized response structure. This spec seems to complicate my code somewhat :)


Apr 5, 2011 at 11:03 AM // reply »
54 Comments

@Ben,

It is further complicated in the case where you need to push things through a proxy. For instance, the curl module in PHP does not support JSON. I am currently using Apache mod proxy for testing, and still unsure what to use in production hopefully Ruby can provide a cross platform/http-server solution.


Apr 5, 2011 at 11:07 AM // reply »
11,314 Comments

@Drew,

Oh yeah - when you need to deal with really HTTP data, proxies always complicate the matter!


Apr 5, 2011 at 2:14 PM // reply »
42 Comments

@Drew Wells, so any problem with using jQuery with processData:false?


Apr 5, 2011 at 2:16 PM // reply »
54 Comments

@Henry,

Nope, I was lucky to find it, otherwise jQuery tries to serialize your data for you. I had the unfortunate experience of debugging this while using a proxy, so after many hours of Wireshark I discovered the issue.


Apr 5, 2011 at 5:01 PM // reply »
3 Comments

If you DeserializeJSON { "jsonrpc":2.0, "error":null, "result":"Blam!" }, you will not get back the original NULL value because ColdFusion9 cannot understand it.

On the other hand, if you ever use Railo 3.2, the result is even more interesting. When Railo encounter a null value, the struct key (in this case, "error") will be lost.

See my post regarding to DeserializeJSON() with the Railo team:

https://issues.jboss.org/browse/RAILO-1117


Apr 5, 2011 at 7:26 PM // reply »
11,314 Comments

@Peter,

Hmm, looks like Railo is using the same "null query value" approach where null values become empty strings. Ultimately, I am not sure what the best solution is. Since we are talking between two systems, it definitely gets tricky!!


Apr 5, 2011 at 11:22 PM // reply »
10 Comments

I've had good luck using Jackson for serializing/deserializing JSON with CF. It won't map to CFC instances, but it can handle nulls. It can work from cfmx-9, is very fast, and can be made to send integers as integers rather than floats.


Apr 6, 2011 at 7:09 AM // reply »
1 Comments

Lots of great information and inspiration, which we all need! I really appreciate the efforts made by you for this. Well Done! Thanks for sharing the information with us.


Apr 6, 2011 at 8:45 AM // reply »
11,314 Comments

@Mark,

Looks interesting (I just Googled "Jackson JSON" and I assume I found the right thing). Do you have problems with it converting strings to numbers? That's one of the biggest issues with CF-native JSON conversions that I see.

@Rupali,

Glad you find this helpful :)


Apr 6, 2011 at 4:46 PM // reply »
10 Comments

@Ben
It depends on where the data you're serializing comes from. You might have to do a lot of javaCast()'s. You also have to watch out for CF converting all your struct keys to uppercase, unless you use array notation (since JSON is case sensitive). However, something like a cfquery (if comes from jdbc, not queryNew()) -- the data is already of the right type.


Apr 7, 2011 at 10:25 PM // reply »
11,314 Comments

@Mark,

Thanks for the update. So far, the CF stuff hasn't been causing too much of an issue. But, we did just launch a beta API to the client application this afternoon. Soon, we'll see if "2" getting converted to 2.0 in the JSON will cause any type-mismatch errors (fingers crossed).



Post A Comment

Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.

Please review the following issues:

Author Name:


Author Email:

Author Website:

Comment:

Supported HTML tags for formatting: <strong>bold</strong>   <em>italic</em>   <code>code</code>







  • Help Wanted - Find Your Next ColdFusion Job
Ben Nadel's Company - Epicenter Consulting Recent Blog Comments
Jun 18, 2013 at 9:20 PM
Mapping AngularJS Routes Onto URL Parameters And Client-Side Events
I couldn't find examples of passing multiple arguments using the when() routing statement so figured out through trial and error that you can pass multiple arguments using the following format: .whe ... read »
Jun 18, 2013 at 3:39 PM
Experimenting With The Amazon Simple Storage Service (S3) API Using ColdFusion
Hi Ben, THANKS! While not bleeding edge, it is new to me & I like learning new things every day! ... read »
Jun 18, 2013 at 12:30 PM
Disabling Auto-Correct And Auto-Capitalize Features On iPhone Inputs
Also spellcheck="false" should be mentioned as part of html5 specs ... read »
Jun 18, 2013 at 8:40 AM
Using Named Functions Within Self-Executing Function Blocks In Javascript
Hi Ben, you forgot to mention the most important thing for named self-executing functions - they can be referenced by name ONLY inside their execution context (which is parens in this case), it mean ... read »
dee
Jun 18, 2013 at 7:01 AM
My Safari Browser SQLite Database Hello World Example
hai ben, this program is really good i could understand the concept but i dint know how to save it and how to open it as you have done in the video can u give that details pls ... read »
Jun 18, 2013 at 6:04 AM
Clearing Inline CSS Properties With jQuery
Thanks a lot for for post! It helped me a lot... after being stuck since 24 hrs.. found solution from your post. Thanks again! ... read »
Jun 18, 2013 at 2:31 AM
SOTR 2013 - The Best Conference I Never Went To
I keep watching it, should keep me happily distracted until SotR14 ;) ... read »
Jun 17, 2013 at 9:45 PM
What If All User Interface (UI) Data Came In Reports?
@Jonah, As I was reading what you wrote, it occurred to me that maybe I do something similar to that in some of my client-side code. In an application I'm working on, there are a bunch of unrelated ... read »
InVision App - Prototyping Made Beautiful With Prototyping Tools