Today I released a ColdFusion WebSocket Gateway on RIAForge and Github. The name pretty much says it all. It is a event gateway for messaging between ColdFusion and conforming clients via the WebSocket protocol. The gateway is based on Nathan Rajlich's Java-WebSocket server implementation, which I updated to support both WebSocket draft 75 and draft 76 clients. For more info on how to install and use this gateway see the Github wiki page.
Last week Ray Camden asked if it was possible to listen for data loaded events with CFTREE. I had done some work with CFTREE in the past and I knew something like this should be possible. After some quick investigation I put together a quick and dirty example to show how you could be notified when new nodes are loaded for a tree.
Last year I put together JSONUtil as a proof of concept solution to the issue of ColdFusion's implicit type conversion during JSON serialization. There were some issues with the 1.0 release, and I've had a few people submit patches, but because I had considered the project an experiment I didn't really take the time to update the official release.
Well, last week I was working on an AJAX project where I was making XHR requests to ColdSpring remote proxies using ColdFusion's built in JSON return format when I began running into issues with implicit type conversion. Specifically I had a method that should have returned a query with string values, however numeric strings were getting converted to decimal numbers. (For example the string "001" was being converted to number 1.0.) Because I was already using ColdSpring to generate the proxies I decided to put together a JSONUtil based ColdSpring advice component to handle the serialization. The advice turned out being so handy I thought I'd package it up and include it in the JSONUtil release.
Just a quick post to let folks know the code and unit tests for JSONUtil are now in SVN at RIAForge.
After getting into another discussion last week about the problems with Serialize/DeserializeJSON and ColdFusion's implicit type conversion I decided to try to do something about it. Over the weekend I put together a proof of concept which I've released as JSONUtil. From the RIAForge project site:
The JSONUtil project currently consists of the JSONUtil component. This component has two public methods, serialize and deserialize, which have method signatures similar to ColdFuison 8's built in Serialize/DeserializeJSON functions. The JSONUtil deserialize method takes the same parameters as DeserializeJSON, JSONVar and strictMapping, and should produce the same results as that function. The JSONUtil serialize method takes the var and serializeQueryByColumns parameters, just as ColdFusion 8's built in SerializeJSON function, however this method also takes an optional third parameter, strictMapping. If the strictMapping parameter is ignored the serialize method should produce the same results as ColdFusion 8's built in SerializeJSON function. If the Boolean strictMapping parameter is set to true then the serialize method attempts to convert the ColdFusion data to a JSON string using underlying Java/SQL data types as opposed to using ColdFusion's implicit type conversion conventions.
The code for the JSONUtil component is based on that of the json.cfc from the CFJSON project, http://www.epiphantastic.com/cfjson. This project probably would not have happened were it not for CFJSON. Thank you to Jehiah Czebotar, Thomas Messier, and everyone who has contributed to the CFJSON project.
To expand on the RIAForge description a bit further, the strictMapping attribute I've added to the serialize method forces the CF data to be serialized based on it's underlying Java data type. For example the following code:
<cfset x = "123" />
<cfoutput> #JSONUtil.serialize(var=x, strictMapping=true)# </cfoutput>
will produce the following JSON string:
SerializeJSON or JSONUtil.serialize without the strictMapping attribute will produce the following JSON string:
The strictMapping attribute also applies to query data as well. If you have a varchar column, its data will always be serialized as string data, even if the string is a numeric or Boolean value in ColdFusion. The strictMapping option also allows you to use JavaCast to help ensure your data values are serialized properly.
There is, however, one caveat to the strictMapping option. In ColdFusion most values are stored as strings. This means that both x and y below:
<cfset y = 123 />
will be serialized as:
If you want numeric values to be serialized as such when using strictMapping you will need to use the Val or JavaCast functions:
<cfset y = JavaCast("int",123) />
(Note: you do not need to do this for query values as query columns are automatically cast to the appropriate Java type by JSONUtil.)
So head over to RIAForge and check it out, and be sure to report any issues via the bug tracker.
I've run into a couple of ColdFusion quirks over the past few days that I thought I'd share. (I should note that these were observed on Adobe CF 8.)
SerializeJSON and Boolean Strings
If you try to serialize the strings "Yes","No","True" or "False" using SerializeJSON, ColdFusion will convert these strings to boolean values. (i.e. "Yes" becomes true, "False" becomes false). This is because ColdFusion is weakly typed and uses some pretty liberal implicit conversion rules when it comes to boolean evaluation. I see this as an issue for the purposes of searializing and deserializing JSON for two reasons. First, there is the potential to lose data. If you serialize the string "Yes" and then deserialize the JSON that ColdFusion generates you are left with true, which is obviously a totally different value than what you started with. Second, it is not really consistent behavior because SerialzeJSON does not convert 1 or 0 (also ColdFusion booleans) to the boolean values true and false. I think the better approach here would be to serialize all strings as strings and only serialize "real" boolean values as booleans.
The other inconsistency I ran into was with IsXML. If you pass something other than a string to IsXML the function throws an error. This is different than the documented behavior which states:
True, if the function parameter is a string that contains well-formed XML text; False, otherwise.
This is also different than the other CFML decision functions which simply return false if passed a function parameter they can't handle. (See IsXmlAttribute for example.)
I think the IsXML issue could definitely be consider a bug, and while the SerializeJSON issue is a little fuzzy, I've gone ahead and reported both as bugs.
As you may have heard Ray Camden and Rob Gonda recently made some updates to RIAForge which allow project owners to share SVN access. After this update Ray was kind enough to give me access to the ColdFire repository and since then I've done some reorganizing. So, what will you find in the ColdFire SVN repo?
A little over a week ago I became aware a 0-day security exploit in ColdFire. I finally have a working fix which Ray has just released over at RIAForge. I strongly recommend that all ColdFire users download and install the latest version (1.003) as soon as possible.