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 »
319 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,238 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,238 Comments

@Donnie,

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


Jan 18, 2010 at 9:53 AM // reply »
11,238 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 »
319 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,238 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,238 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,238 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,238 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,238 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 »
63 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
May 22, 2013 at 7:52 AM
Nested Views, Routing, And Deep Linking With AngularJS
Hi, Just a quick thank you. As it happens, for my own purposes, the pending ui-router work being done in native angular is likely the one I'll adopt, but your exploration, code and documentation of ... read »
May 22, 2013 at 4:43 AM
How Do You Use The ColdFusion CFParam Tag?
'<cfparam>' or 'isDefined()and <cfset>' performs the same task.Is there any difference? ... read »
May 21, 2013 at 7:46 PM
Using Plupload For Drag & Drop File Uploads In ColdFusion
No luck. At least I have uncovered the cause, URLScan 3.1. Here is what I see in the IIS log when a file is over 30mb. 2013-05-21 23:29:05 10.105.45.128 GET /plupload/assets/jquery/jquery-1.8. ... read »
May 21, 2013 at 6:12 PM
Using Plupload For Drag & Drop File Uploads In ColdFusion
Ben, I did not see you after Pete Freitag's Lockdown session at cfObjective but he said that IIS sets file size limits at 30MB by default which just happened to be the threshold for file size when ... read »
May 21, 2013 at 11:51 AM
Ask Ben: Parsing Very Large XML Documents In ColdFusion
Looking at my first ever XML document that I have to parse and put into MS SQL 2000 with CF8. I get it to list the desired Field name, many times over, and have a long list of this field name displa ... read »
May 21, 2013 at 9:25 AM
Turning Off and On Identity Column in SQL Server
you are awesome..i am lucky to get this blog between such a garbage one....Thanks, Prashant ... read »
May 20, 2013 at 4:38 PM
Using A Dynamic Column Name With ValueList() In ColdFusion
@Dana, Your confusion is well founded, since this is a very confusing features. In fact, it ONLY works if you use array notation. Meaning, that this: arrayToList( query[ "columnName" ] ) ... read »
May 20, 2013 at 4:34 PM
Using A Dynamic Column Name With ValueList() In ColdFusion
I was thinking chicken and the egg, I wouldn't have expected it to work in the valuelist going in I guess. Maybe I just need a beer, long day :) ... read »
InVision App - Prototyping Made Beautiful With Prototyping Tools