Skip to main content
Ben Nadel at CFinNC 2009 (Raleigh, North Carolina) with: Yancy Wharton
Ben Nadel at CFinNC 2009 (Raleigh, North Carolina) with: Yancy Wharton

Extracting JSON Embedded Within A Generate HTML File In ColdFusion

By
Published in

Yesterday, I looked at decoding the output of encodeForJavaScript() in ColdFusion. That post was a stepping stone for today's exploration; which is extracting said serialized JSON payload from a generated HTML file in ColdFusion.

As I mentioned yesterday, I often use the encodeForJavaScript() function to embed ColdFusion data into a JavaScript context. This is helpful when rendering a Single-Page Application (SPA) experience. But, it's also helpful when generating static HTML files.

Consider the following ColdFusion custom tag which takes a filePath and a config object and then generates a static HTML file in which said config is embedded into the page's JavaScript execution:

<cfparam name="attributes.filePath" type="string" />
<cfparam name="attributes.config" type="struct" />

<cfsavecontent variable="fileContent">
	<!doctype html>
	<html lang="en">
	<body>
		<h1>
			Generated By ColdFusion
		</h1>

		<script type="text/javascript">
			window.app = {
				config: JSON.parse(
					//--JSON:BEGIN--//
					"<cfoutput>#encodeForJavaScript( serializeJson( attributes.config ) )#</cfoutput>"
					//--JSON:END--//
				)
			};
		</script>
	</body>
	</html>
</cfsavecontent>

<cfset fileWrite( attributes.filePath, fileContent ) />

Inside of the generated page's <script> tags, I'm using the encodeForJavaScript() function in conjunction with the serializeJson() function to make the config object consumable in the generated client-side JavaScript execution. Notice also that I'm also surrounding the JSON payload with two JavaScript comments: //--JSON:BEGIN--// and //--JSON:END--//. We will later use these comments as parsing markers when extracting the JSON payload.

But first, let's actually generate our static file by invoking this ColdFusion custom tag (generate.cfm):

<cfscript>

	config = [
		title: "My App",
		people: [
			{
				id: 1,
				name: "Kimmie Bo-Bimmie",
				contact: {
					type: "mobile",
					number: "212-555-1199"
				}
			}
		]
	];

	// This will generate a static HTML file with the above config data structure encoded
	// into the HTML page as a JSON payload.
	module
		template = "./generate.cfm"
		filePath = expandPath( "./static.htm" )
		config = config
	;

</cfscript>

If we run this ColdFusion code, we end up with a static HTML file, static.htm, which contains our config data structure as an embedded JSON payload. But, remember that the JSON payload is surrounded by our two comment markers. We can now use those comment markers with the decodeForJavaScript() user defined function (UDF) that I authored yesterday:

<cfscript>

	// Defines our decodeForJavaScript() function from previous blog post.
	include "./fns.cfm";

	// ------------------------------------------------------------------------------- //
	// ------------------------------------------------------------------------------- //

	fileContent = fileRead( "./static.htm", "utf-8" );

	// When we generated the static HTML file, we delineated the JSON payload with
	// JavaScript comments. We can use those comment-markers to locate and extract the
	// JSON from the generated file.
	startMarker = "//--JSON:BEGIN--//";
	startIndex = fileContent.find( startMarker );
	endMarker = "//--JSON:END--//";
	endIndex = fileContent.find( endMarker );

	encodedJson = fileContent
		// Extract the content in between the two JSON markers.
		.mid(
			( startIndex + startMarker.len() ),
			( endIndex - startIndex - startMarker.len() )
		)
		// Remove the surrounding quotes from the JSON.
		.trim()
		.right( -1 ) // Everything but leading-quote.
		.left( -1 )  // Everything but trailing-quote.
	;

	dump(
		label = "Extracted Config",
		var = deserializeJson( decodeForJavaScript( encodedJson ) )
	);

</cfscript>

In this ColdFusion code, I'm extracting the file content in between the two JSON comment markers and I'm stripping-off the surrounding quotes that are needed for the client-side JSON.parse() call. This leaves me with the encoded data. I then use the decodeForJavaScript() UDF which gives me the raw JSON value; which I then deserialize using ColdFusion's native deserializeJson() function.

And, when we run this ColdFusion code, we get the following output:

The JSON payload being parsed in both a JavaScript context and an extracted ColdFusion context.

As you can see, the embedded JSON payload can be parsed and consumed in the JavaScript context using JSON.parse(). Then, from our ColdFusion context, we were able to successfully read-in the static HTML file, extract the embedded and encoded JSON string, parse it, and deserialize it back into a native ColdFusion data structure.

By using this technique, I have a pathway for using a generated HTML file as both a static web page experience and as a persisted data file. This is certainly an uncommon use-case; but, it's one that I have need of.

Want to use code from this post? Check out the license.

Reader Comments

Post A Comment — I'd Love To Hear From You!

Post a Comment

I believe in love. I believe in compassion. I believe in human rights. I believe that we can afford to give more of these gifts to the world around us because it costs us nothing to be decent and kind and understanding. And, I want you to know that when you land on this site, you are accepted for who you are, no matter how you identify, what truths you live, or whatever kind of goofy shit makes you feel alive! Rock on with your bad self!
Ben Nadel