JSON Files As Temporary File Storage In ColdFusion Applications

Posted January 18, 2010 at 9:29 AM by Ben Nadel

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

Jan 18, 2010 at 9:40 AM // reply »
321 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 »
11,314 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 »
26 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 »
11,314 Comments

@Donnie,

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


Jan 18, 2010 at 9:53 AM // reply »
11,314 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 »
321 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 »
9 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 »
11,314 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 »
11,314 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 »
11,314 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 »
11,314 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 »
11,314 Comments

@Ward,

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


May 10, 2011 at 6:34 AM // reply »
1 Comments

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


Apr 5, 2013 at 1:19 PM // reply »
64 Comments

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



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