JSON Files As Temporary File Storage In ColdFusion Applications

Posted January 18, 2010 at 9:29 AM

Tags: ColdFusion

I love databases; but, if I'm writing a small application or proof of concept, often times, I don't want to have to go through the bother of creating a new database and its accompanying Data Source Name (DSN). In cases like this, I'll typically use flat files to persist simple data between application instantiations. In the past, I would have used XML and WDDX to perform the serialization and deserialization of data; but, with ColdFusion 8, I have switched over to JSON (Javascript Object Notation) as my persisted data format of choice.

ColdFusion 8 gave us some great new functionality. Not only did it give us Function-based ways to read and write files - fileRead() and fileWrite() - it also gave us functions for serializing and deserializing JSON data. With these two sets of functions in hand, I quickly found JSON to be a super easy way to quickly write ColdFusion objects to disk and then read them back in.

To demonstrate, take a look at this sample code:

 Launch code in new window » Download code as text file »

  • <!---
  • Get the full file path to the directory in which we are
  • storing our serialized JSON data files.
  • --->
  • <cfset dataDirectory = getDirectoryFromPath(
  • getCurrentTemplatePath()
  • ) />
  •  
  • <!--- Create a basic ColdFusion object. --->
  • <cfset girl = {
  • name = "Joanna",
  • hair = "Brunette",
  • bestAttributes = [
  • "Smile",
  • "Legs"
  • ]
  • } />
  •  
  •  
  • <!---
  • Serialize the ColdFusion data object into a JSON string
  • and write it to disk.
  • --->
  • <cfset fileWrite(
  • "#dataDirectory#data.json",
  • serializeJSON( girl )
  • ) />
  •  
  • <!---
  • Read in serialized JSON string a deserialized it back into
  • a ColdFusion data object.
  • --->
  • <cfset girlFromJSON = deserializeJSON(
  • fileRead( "#dataDirectory#data.json" )
  • ) />
  •  
  •  
  • <!--- Output the ColdFusion data object created JSON. --->
  • <cfdump
  • var="#girlFromJSON#"
  • label="JSON to ColdFusion"
  • />

Here, I'm using serializeJSON() and fileWrite() to store the ColdFusion data to a flat file; then, I'm using fileRead() and deserializeJSON() to turn a flat file back into a ColdFusion object. Like I said - super easy! And, when we run the above code, we get the following output:

 
 
 
 
 
 
JSON Format As A Great Way To Serialize and Deserailzie ColdFusion Data.  
 
 
 

As a comparison to the JSON approach, I figured I'd also show you my older, XML / WDDX approach:

 Launch code in new window » Download code as text file »

  • <!---
  • Get the full file path to the directory in which we are
  • storing our serialized JSON data files.
  • --->
  • <cfset dataDirectory = getDirectoryFromPath(
  • getCurrentTemplatePath()
  • ) />
  •  
  • <!--- Create a basic ColdFusion object. --->
  • <cfset girl = {
  • name = "Joanna",
  • hair = "Brunette",
  • bestAttributes = [
  • "Smile",
  • "Legs"
  • ]
  • } />
  •  
  •  
  • <!--- Serailize the ColdFusion object into a WDDX string. --->
  • <cfwddx
  • action="cfml2wddx"
  • input="#girl#"
  • output="girlWDDX"
  • />
  •  
  • <!--- Write the WDDX data to disk. --->
  • <cfset fileWrite(
  • "#dataDirectory#data.xml",
  • girlWDDX
  • ) />
  •  
  • <!---
  • Read in serialized WDDX string a deserialized it back into
  • a ColdFusion data object.
  • --->
  • <cfwddx
  • action="wddx2cfml"
  • input="#fileRead( '#dataDirectory#data.xml' )#"
  • output="girlFromWDDX"
  • />
  •  
  • <!--- Output the ColdFusion data object created JSON. --->
  • <cfdump
  • var="#girlFromWDDX#"
  • label="WDDX to ColdFusion"
  • />

This does the same thing, so I'm not going to bother showing the CFDump output - trust me, it does the same exact thing. The difference in the code is that we are using the CFWDDX tag to serialize and deserialize the ColdFusion data (to and from XML). Since there is no CFWDDX Function - it's only available in tag form - we have to add an extra step to perform the serialization (the file read and WDDX deserialization can still be lumped into one step).

While the difference in invocation is not terribly huge, there's just something about the serializeJSON() and deserializeJSON() functions that I find very natural and easy to use. Plus, the data that gets generated as JSON is much smaller, and is, in my opinion, easier to understand and modify, than its WDDX data format counterpart.

JSON Data Format

{"BESTATTRIBUTES":["Smile","Legs"], "NAME":"Joanna", "HAIR":"Brunette"}

WDDX Data Format

<wddxPacket version='1.0'> <header/> <data> <struct> <var name='BESTATTRIBUTES'> <array length='2'> <string>Smile</string> <string>Legs</string> </array> </var> <var name='NAME'> <string>Joanna</string></var>< var name='HAIR'> <string>Brunette</string> </var> </struct> </data> </wddxPacket>

Maybe it's because I do so much work with AJAX and jQuery, but to me, the JSON data form is basically like reading English, where as I find the WDDX XML format requires actual mental parsing. Of course, I'm not here to sell you on JSON vs. XML (with or without WDDX). I'm just saying that ever since ColdFusion 8 adding JSON-based functions, JSON has become my flat file data storage format of choice; there's something about it that just feels really easy and natural to work with.

Download Code Snippet ZIP File

Post Comment  |  Ask Ben  |  Print Page





Reader Comments

Jan 18, 2010 at 9:40 AM // reply »
226 Comments

My only concern with this approach is how serializeJSON is typeless. If you have data you meant to be considered a string, serializeJSON will munge it. It can do things like changing 1 to 1.0. javacast() can help, but it's something you have to watch out for.


Jan 18, 2010 at 9:46 AM // reply »
7,486 Comments

@Raymond,

Yeah, that's true. Going from typeless to typed, ColdFusion has to make some guess work. For example, if I added:

hotness: 9

... to my data struct, the JSON becomes:

HOTNESS: 9.0

... and the WDDX becomes:

<string>9</string>

So, the WDDX is more "accurate" based on the underlying ColdFusion data types (string based everything :)), but it's not necessarily accurate in the intent.

Of course, the "intent" of data storage is just that - data storage; as such, it's definitely a benefit that WDDX works better to that extent. However, I have to say that I have never personally run into an issue with JSON usage.... at least not yet :)


Jan 18, 2010 at 9:48 AM // reply »
5 Comments

Ben, just one thing to note (you may already be aware of this), and it's something I ran into recently, for this type of scenario it may be important to use the second parameter of the serializeJSON and deserializeJSON functions, mainly because by default serializeJSON doesn't distinguish between a CF Structure and a CF Query. It serializes both as structures. Did a post about this http://bit.ly/8PRfba.


Jan 18, 2010 at 9:52 AM // reply »
21 Comments

Interesting approach. With CF9 using ORM is great for stuff like this where you want to store data but don't want the hassle of dealing with databases.


Jan 18, 2010 at 9:52 AM // reply »
7,486 Comments

@Donnie,

"The Don", good point. I forgot about that.


Jan 18, 2010 at 9:53 AM // reply »
7,486 Comments

@Sam,

Exactly. I find it especially awesome with "proof of concept" type applications where just want to do a little experimentation.


Jan 18, 2010 at 9:56 AM // reply »
226 Comments

Something else I'll add - and I blogged on this a few weeks back - JSON is a super quick way to log complex data to a log as well. Obviously you wouldn't want to cflog something big, but for quick and dirty logging it works great.


Jan 18, 2010 at 10:07 AM // reply »
5 Comments

@Ben I am so going to do an avatar for that although it is not warranted at all! :)


Jan 18, 2010 at 10:28 PM // reply »
3 Comments

You can in fact have typed deserialization with JSON, though I doubt ColdFusion will handle the magic for you the way it handles (de-)serialization for untyped object graphs.

Since JSON is just a JavaScript object literal, and in javascript an object has a type instead of is of type (i.e. it has a prototype), you could serialize an object graph with its type.

See http://tobyho.com/Typed_Deserialization_with_JSON


Jan 19, 2010 at 10:26 AM // reply »
7,486 Comments

@Ray, @Donnie,

I found your comments though provoking fodder for a follow-up post:

http://www.bennadel.com/blog/1820-Maintaining-ColdFusion-Query-Data-Type-Integrity-Throughout-The-Serialization-Life-Cycle.htm


Jan 19, 2010 at 1:04 PM // reply »
14 Comments

One question:

That table output; is that some kind of default behaviour of CF or did you do some transformation on the data?


Jan 19, 2010 at 1:05 PM // reply »
7,486 Comments

@Kristopher,

That is the way the CFDump tag outputs data.


Jan 19, 2010 at 2:57 PM // reply »
14 Comments

That's beautiful! Where does it output to? What environment is that? I can only associate this to my TDD in Visual Studio when I'm looking at my output window...


Jan 20, 2010 at 11:18 PM // reply »
7,486 Comments

@Kristopher,

It outputs directly to the current output buffer. The CFDump is a ColdFusion construct, so you'd have to be using ColdFusion.


Jan 24, 2010 at 12:20 PM // reply »
2 Comments

My version of ColdFusion 8 chokes on the code for creating the ColdFusion object that you provide. Do you have a reference that I can explore for building objects the way you show? I see references to the cfobject tag but I can find nothing that looks like your code.


Jan 24, 2010 at 10:06 PM // reply »
7,486 Comments

@Ward,

This code was built using ColdFusion 8. It's possible that you are missing one of the Updates / Patches. I think the nested implicit struct / array notation might be something that was done in one of the hot fixes.


Jan 25, 2010 at 1:51 AM // reply »
2 Comments

Thanks for the quick response! I ran the code on my HostMySite account and it ran correctly. Now I need to update my Development ColdFusion installation and look deeper into the implicit struct / array notation. I see you covered it in an earlier blog entry.

BTW, I'm becoming a great fan of yours! I like the way you share your knowledge and following your routines is a great way to learn.


Jan 25, 2010 at 9:22 PM // reply »
7,486 Comments

@Ward,

Oh great - glad we narrowed it down. And, thank you very much for the kind words :)


Post Comment  |  Ask Ben

Recent Blog Comments
Mar 11, 2010 at 9:29 PM
Tim Cracked The GMail - CFMailPart Puzzle!
I've been wrestling with the CFMAIL tag and CFMAILPARTS for several days now and have found issues with the CF implementation even in CF9! What I have learned so far is: 1. Using only one CFMAILPART ... read »
Mar 11, 2010 at 6:09 PM
Ask Ben: Building An AJAX, jQuery, And ColdFusion Powered Application
@Eric, Neat trick, I was able to get rid of most of the lines of whitespace following your advice. Some whitespace still remains. With a bit of playing around, I found that the remaining whitespa ... read »
Mar 11, 2010 at 4:56 PM
Ask Ben: Building An AJAX, jQuery, And ColdFusion Powered Application
I've struggled with returning JSON from ColdFusion CFCs for a while because I (mysteriously) get lots of white space/new lines that appear before the actual JSON result (check the response in Firebug ... read »
Mar 11, 2010 at 3:24 PM
Ask Ben: Using jQuery To Act On A Click Event Based On The Target Element
@TripeL, Awesome :) Glad it was helpful. ... read »
Mar 11, 2010 at 3:23 PM
Ask Ben: Using jQuery To Act On A Click Event Based On The Target Element
WOW...that's what I'm looking for. The code examples are very helpful. Thanks ... read »
Mar 11, 2010 at 1:20 PM
What Is The Best Time Of Day To Workout?
Well I am glad I stick to mid afternoon / evening work outs. Interesting find! ... read »
Mar 11, 2010 at 1:13 PM
CFHTTPSession.cfc For Multi-CFHttp Requests With Maintained Session
It worked for what I needed perfectly the first try... this is huge, you have made my week! ... read »
Mar 11, 2010 at 12:54 PM
Using Appropriate Status Codes With Each API Response
I forgot to mention that using this application stack allows me to separate as much of the core/business logic into the API Library which leaves the web applications just to handle presentation layer ... read »