Ben Nadel
On User Experience (UX) Design, JavaScript, ColdFusion, Node.js, Life, and Love.
I am the chief technical officer at InVision App, Inc - a prototyping and collaboration platform for designers, built by designers. I also rock out in JavaScript and ColdFusion 24x7.
Meanwhile on Twitter
Loading latest tweet...
Ben Nadel at cf.Objective() 2011 (Minneapolis, MN) with:

JSON Files As Temporary File Storage In ColdFusion Applications

By Ben Nadel on
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:

  • <!---
  • 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:

  • <!---
  • 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.




Reader 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.

@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 :)

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.

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.

@Sam,

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

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.

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

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...

@Kristopher,

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

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.

@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.

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.

Hi

I very much like the samples you show. They are really good and give much information.
What I really don't like is that all examples are girl's related. It is kind of inappropriate.
Or if you post some samples about girls then post some about men. I read it and i get tired reading about girls all over again :)

Kind regards
Diana Dimitrova

Re: <string>9</string>

It should not be a string. It should be an int primitive - but that's a different argument.

=========================
hotness: 9

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

HOTNESS: 9.0

... and the WDDX becomes:

<string>9</string>
=========================

Here's where the epiphany of type-safety dawns ... ;-)