I have been struggling with syntax highlighters for several days. I follow the instructions, put the correct commands in the head, use the corrrect instructions in my post and still nothing. This is one of the pages I refer to in order to see the correct instructions:
http://www.cyberack.com/2007/07/adding-syntax-highlighter-to-blogger.html
Here is a test of syntax highlighter software:
<?php
$example = range(0, 9);
foreach ($example as $value)
{
echo $value;
}
Let's see how the test turns out
Here is another test:
</pre class="brush: ColdFusion">
<html>
<body>
<h1>My First Heading</h1>
<p>My first paragraph.</p>
</body>
</html>
Here is another test:
<pre class="brush: html">
<html>
<body>
<h1>My First Heading</h1>
<p>My first paragraph.</p>
</body>
</html>
</pre>
Here is another test:
<code class="brush: html">
<html>
<body>
<h1>My First Heading</h1>
<p>My first paragraph.</p>
</body>
</html>
</code>
Here is another test:
<pre class="brush: cf"><p> </p>
<pre class="brush: cf"><p> </p>
<p> </p><p> </p>
<p><span style="white-space: pre;"> </span></p>
<p><code>[{'text':'Jewelry','id':'1',"cls":"folder"},
{'text':'Vintage Clothing and Accessories',
'id':'2',"cls":"folder"},
{'text':'Spices','id':'3',"cls":"folder"},
{'text':'Art','id':'4',"cls":"folder"},
{'text':'Collectibles','id':'5',"cls":"folder"},
{'text':'Books','id':'6',"cls":"folder"},
{'text':'Teas','id':'7',"cls":"folder"},
{'text':'Clothing','id':'8',"cls":"folder"},
{'text':'Exercise','id':'10',"cls":"folder"},
{'text':'Send A Little Something','id':'11',"cls":"folder"},
{'text':'My New Category','id':'12',"cls":"folder"},
{'text':'Another New Category','id':'14',"cls":"folder"}]
How do you emulate this response? First you must know what the [ and the { indicate.
The [ indicates you are returning an array. The { indicates you are returning a structure. Since the [ is on the outside, you need to build a structure inside an array.
So first you execute a query. Then you create an array, loop through the query. For each loop create a structure that is appended to the array.
How?
Here is an example:
SELECT CategoryID, CategoryName
FROM CategoriesTable
WHERE CategoryID = #arguments.node#
ORDER BY CategoryID
Now set up your array
Set the value for your index
Loop through the query
Define your structure
Load the structure (note that you can load the array several ways: cfset mystruct.id returns an uppercase id and value, cfset mystruct["id"] returns a lowercase id and value. Since ExtJS expects lowercase values I use mystruct["id"].
Load the structure into the array
Increment the index
Continue until the loop is completed
Then all you need to do is return the array users to the calling program
Make sure your function has ,?returnformat="JSON">
// -->
</code></p></pre>
<p><code>
<p> </p>
<p> </p>
<p>I hope this helps. In the future I will post full examples.</p>
<p> </p>
<p> </p>
<p> </p>
</code></p>
<?php
$example = range(0, 9);
foreach ($example as $value)
{
echo $value;
}
<script>
document.write("<p>My First JavaScript</p>");
</script>
<html>
<body>
<h1>My First Heading</h1>
<p>My first paragraph.</p>
</body>
</html>
<cfcomponent output="false">
<cfsetting showdebugoutput="false">
<!---<cfsetting showdebugoutput="no"> ---><!--- To supress any debugging code that will upset the json return --->
<cffunction name="getContacts" access="remote" returnFormat="json" returntype="any" >
<!---<cfargument name="limit" default="10">
<cfargument name="start" default="1">
<cfargument name="sort" default="ItemID">
<cfargument name="dir" default="ASC">--->
<!---<cfinclude template="json.cfc" />---> <!---cfJSON file--->
<cfparam default="7" name="form.RECORDID">
<!---<cfinclude template= "../cflibJSON/cflibJSON.cfm">---> <!---jsonencode/jsondecode/isJSON from cflib.org--->
<cfquery datasource="#request.dsn#" name="getContacts">
SELECT id
, firstName
, lastName
, company
, title
, pic
, email
, webPage
, imaddress
, homePhone
, busPhone
, mobPhone
, fax
, mailto
, bAddress
, hAddress
, mailingAddress
FROM contactform
<cfif isDefined("form.RECORDID")>
where id = #form.RECORDID#
<cfelse>
where id = 1
</cfif>
</cfquery>
<!--- <cfif url.recordID not equal 1>--->
<!---<cfif getContacts.id equal 1>--->
<cfscript>
thestruct = StructNew();
rtnStruct = StructNew();
thestruct['success'] = StructNew();
thestruct['success'] = true;
thestruct['data'] = StructNew();
thestruct['data']['id'] = getContacts.id;
thestruct['data']['company'] = Replace(getContacts.company, chr(13) & chr(10), ' ','ALL');
thestruct['data']['title'] = getContacts.title;
thestruct['data']['firstname'] = getContacts.firstName;
thestruct['data']['lastname'] = getContacts.lastName;
thestruct['data']['pic'] = Replace(getContacts.pic, '\', '','ALL');
thestruct['data']['email'] = Replace(getContacts.email, chr(13) & chr(10), ' ','ALL');
thestruct['data']['webpage'] = getContacts.webPage;
/*REplace(getContacts.webPage, chr(35), '','ALL');
*/
thestruct['data']['imaddress'] = Replace(getContacts.imAddress, chr(13) & chr(10), ' ','ALL');
thestruct['data']['homephone'] = Replace(getContacts.homePhone, chr(13) & chr(10), ' ','ALL');
thestruct['data']['busphone'] = Replace(getContacts.busPhone, chr(13) & chr(10), ' ','ALL');
thestruct['data']['mobphone'] = Replace(getContacts.mobPhone, chr(13) & chr(10), ' ','ALL');
thestruct['data']['fax'] = Replace(getContacts.fax, chr(13) & chr(10), ' ','ALL');
thestruct['data']['mailto']= getContacts.mailto;
thestruct['data']['baddress'] = getContacts.baddress;
thestruct['data']['haddress'] = getContacts.haddress;
/* thestruct['data']['hAddress'] = Replace(getContacts.hAddress, chr(13) & chr(10), ' ','ALL');*/
thestruct['data']['mailingaddress'] = Replace(getContacts.mailingAddress, chr(13) & chr(10), ' ','ALL');
/* thestruct['data']['state'] = getContacts.state;*/
/* thestruct['data']['dob'] = dateFormat(getContacts.dob, "mm/dd/yyyy");*/
/* thestruct['data']['dob'] = '10/27/1955';*/
/* thestruct['data']['fee'] = getContacts.fee;*/
/* thestruct['data']['fee'] = '5';*/
/* return serializejson(preservesinglequotes(thestruct));*/
return serializejson(thestruct);
rtnStruct.success = true;
rtnStruct.data = getContacts;
return serializeJSON(rtnStruct,false);
</cfscript>
<cfset session.id = "#getContacts.id#">
<cfset session.pic = "#getContacts.pic#">
<!--- <cfset result = thestruct>--->
<!--- <cfelse>--->
<!--- <cfset result ="{success:true,data:{id:'1',firstName:'Donna',lastName:'Hines',company:'SendaLittleSomething',title:'Mrs',pic:'img/jorger.jpg',email:'fleminghines@verizon.net',webPage:'http://www.sendalittlesomething.com',imAddress:'',homePhone:'410.877.0109',busPhone:'999 999-9999',mobPhone:'410.746.5291',fax:'443.352.7300',bAddress:'1308 Terry Way Fallston, MD 2107',hAddress:'1308 Terry Way Fallston, MD 21047',mailingAddress:'mailToBAddress'}}">--->
<!--- <cfset result = "{success:true,data:{id:'1',firstName:'Donn',lastName:'Hines',company:'Send a Little Something',title:'Mrs',pic:'img/jorger.jpg',email:'fleminghines@verizon.net',webPage:'http://www.miamicoder.com',imAddress:'',homePhone:'',busPhone:'555 555-5555',mobPhone:'',fax:'',bAddress:'123 Acme Rd 001 nMiami, FL 33133',hAddress:'',mailingAddress:'mailToBAddress'}}">--->
<!---<CFCONTENT
TYPE="text/plain"
RESET="Yes"><CFOUTPUT>#result#</CFOUTPUT>--->
<!--- </cfif>--->
<!---<cfset result= thestruct>--->
<!--- <cfset result = "{success: true, data:{recordid:'1', first:'Jack', last:'Slocum', company:'Ext JS', email:'support@extjs.com', state:'OH', dob:'04/15/2007', fee:'50'} }">
<CFCONTENT
TYPE="text/plain"
RESET="Yes"><CFOUTPUT>#result#</CFOUTPUT>--->
<!---<cfelse>
<cfset result = "{success: true, data:{recordid:'1', first:'Jack', last:'Slocum', company:'Ext JS', email:'support@extjs.com', state:'OH', dob:'04/15/2007', fee:'50'} }">
<CFCONTENT
TYPE="text/plain"
RESET="Yes"><CFOUTPUT>#result#</CFOUTPUT>
</cfif>--->
<!---<cfinvoke component="JSON" method="encode" data="#thestruct#" returnvariable="result" />--->
<!---<cfset result1 = "{data:{recordid:'1', first:'Jack', last:'Slocum', company:'Ext JS', email:'support@extjs.com', state:'OH', dob:'04/15/2007', fee:'50'}, success: true }">--->
<!--- <CFCONTENT
TYPE="text/plain"
RESET="Yes"><cfoutput>#jsonencode(thestruct)#</cfoutput>--->
<!---<CFCONTENT
TYPE="text/plain"
RESET="Yes"><cfoutput>#thestruct#</cfoutput>--->
<!--- <cfoutput>#jsonencode(thestruct)#</cfoutput>
<cfoutput>#result#</cfoutput>
<cfoutput>#result1#</cfoutput>--->
</cffunction>
<cffunction name="getFirstName" access="remote" output="false" returntype="any" returnformat="json">
<cfargument name="RECORDID" type="numeric" required="false" />
<cfset var output = "" />
<cfset var q = "" />
<!---<cfparam name="arguments.id" default="1">--->
<cftry>
<cfquery name="q" datasource="#request.dsn#">
SELECT id as RECORDID, first as FIRSTNAME
FROM contactform
where id = #arguments.RECORDID#
</cfquery>
<cfscript>
//format the query for ExtJS json
compObj = CreateObject("component", "cf_extjs");
extjs_jsonVar = compObj.qry2json(q,0,100);
</cfscript>
<cfcatch type="database">
<cfset q="Data Set Creation Error.">
</cfcatch>
</cftry>
<!---<cfoutput>
#SerializeJSON(q)#
<!--- #user.details.email#--->
</cfoutput>--->
<!---<cfreturn q />--->
<cfreturn extjs_jsonVar />
</cffunction>
<cffunction name="getLastName" access="remote" output="false" returntype="any" returnformat="json">
<!--- <cfargument name="id" type="numeric" required="false" />--->
<cfset var output = "" />
<cfset var q = "" />
<!---<cfparam name="arguments.id" default="1">--->
<cftry>
<cfquery name="q" datasource="#request.dsn#">
SELECT id as RECORDID, last as LASTNAME
FROM contactform
order by recordid
</cfquery>
<!--- <cfscript>
q = QueryNew("id,GENER_NAME,sort_order");
QueryAddRow(q,3);
QuerySetCell(q,"id",1,1);
QuerySetCell(q,"GENER_NAME","Comedy",1);
QuerySetCell(q,"sort_order",0,1);
QuerySetCell(q,"id",2,2);
QuerySetCell(q,"GENER_NAME","Drama",2);
QuerySetCell(q,"sort_order",1,2);
QuerySetCell(q,"id",3,3);
QuerySetCell(q,"GENER_NAME","Mystery",3);
QuerySetCell(q,"sort_order",2,3);
--->
<cfscript>
//format the query for ExtJS json
compObj = CreateObject("component", "cf_extjs");
extjs_jsonVar = compObj.qry2json(q,0,100);
</cfscript>
<cfcatch type="database">
<cfset q="Data Set Creation Error.">
</cfcatch>
</cftry>
<!---<cfoutput>
#SerializeJSON(q)#
<!--- #user.details.email#--->
</cfoutput>--->
<!---<cfreturn q />--->
<cfreturn extjs_jsonVar />
</cffunction>
<!--- <cfcomponent displayname="JSON" output="No">--->
<cffunction name="jsonencode" access="remote" returntype="string" output="No"
hint="Converts data from CF to JSON format">
<cfargument name="data" type="any" required="Yes" />
<cfargument name="queryFormat" type="string" required="No" default="query" /> <!-- query or array -->
<cfargument name="queryKeyCase" type="string" required="No" default="lower" /> <!-- lower or upper -->
<cfargument name="stringNumbers" type="boolean" required="No" default=false >
<cfargument name="formatDates" type="boolean" required="No" default=false >
<cfargument name="columnListFormat" type="string" required="No" default="string" > <!-- string or array -->
<!--- VARIABLE DECLARATION --->
<cfset var jsonString = "" />
<cfset var tempVal = "" />
<cfset var arKeys = "" />
<cfset var colPos = 1 />
<cfset var i = 1 />
<cfset var column = ""/>
<cfset var datakey = ""/>
<cfset var recordcountkey = ""/>
<cfset var columnlist = ""/>
<cfset var columnlistkey = ""/>
<cfset var dJSONString = "" />
<cfset var escapeToVals = "\\,\"",\/,\b,\t,\n,\f,\r" />
<cfset var escapeVals = "\,"",/,#Chr(8)#,#Chr(9)#,#Chr(10)#,#Chr(12)#,#Chr(13)#" />
<cfset var _data = arguments.data />
<!--- BOOLEAN --->
<cfif IsBoolean(_data) AND NOT IsNumeric(_data) AND NOT ListFindNoCase("Yes,No", _data)>
<cfreturn LCase(ToString(_data)) />
<!--- NUMBER --->
<cfelseif NOT stringNumbers AND IsNumeric(_data) AND NOT REFind("^0+[^\.]",_data)>
<cfreturn ToString(_data) />
<!--- DATE --->
<cfelseif IsDate(_data) AND arguments.formatDates>
<cfreturn '"#DateFormat(_data, "medium")# #TimeFormat(_data, "medium")#"' />
<!--- STRING --->
<cfelseif IsSimpleValue(_data)>
<cfreturn '"' & ReplaceList(_data, escapeVals, escapeToVals) & '"' />
<!--- ARRAY --->
<cfelseif IsArray(_data)>
<cfset dJSONString = createObject('java','java.lang.StringBuffer').init("") />
<cfloop from="1" to="#ArrayLen(_data)#" index="i">
<cfset tempVal = jsonencode( _data[i], arguments.queryFormat, arguments.queryKeyCase, arguments.stringNumbers, arguments.formatDates, arguments.columnListFormat ) />
<cfif dJSONString.toString() EQ "">
<cfset dJSONString.append(tempVal) />
<cfelse>
<cfset dJSONString.append("," & tempVal) />
</cfif>
</cfloop>
<cfreturn "[" & dJSONString.toString() & "]" />
<!--- STRUCT --->
<cfelseif IsStruct(_data)>
<cfset dJSONString = createObject('java','java.lang.StringBuffer').init("") />
<cfset arKeys = StructKeyArray(_data) />
<cfloop from="1" to="#ArrayLen(arKeys)#" index="i">
<cfset tempVal = jsonencode( _data[ arKeys[i] ], arguments.queryFormat, arguments.queryKeyCase, arguments.stringNumbers, arguments.formatDates, arguments.columnListFormat ) />
<cfif dJSONString.toString() EQ "">
<cfset dJSONString.append('"' & arKeys[i] & '":' & tempVal) />
<cfelse>
<cfset dJSONString.append("," & '"' & arKeys[i] & '":' & tempVal) />
</cfif>
</cfloop>
<cfreturn "{" & dJSONString.toString() & "}" />
<!--- QUERY --->
<cfelseif IsQuery(_data)>
<cfset dJSONString = createObject('java','java.lang.StringBuffer').init("") />
<!--- Add query meta data --->
<cfif arguments.queryKeyCase EQ "lower">
<cfset recordcountKey = "recordcount" />
<cfset columnlistKey = "columnlist" />
<cfset columnlist = LCase(_data.columnlist) />
<cfset dataKey = "data" />
<cfelse>
<cfset recordcountKey = "RECORDCOUNT" />
<cfset columnlistKey = "COLUMNLIST" />
<cfset columnlist = _data.columnlist />
<cfset dataKey = "data" />
</cfif>
<cfset dJSONString.append('"#recordcountKey#":' & _data.recordcount) />
<cfif arguments.columnListFormat EQ "array">
<cfset columnlist = "[" & ListQualify(columnlist, '"') & "]" />
<cfset dJSONString.append(',"#columnlistKey#":' & columnlist) />
<cfelse>
<cfset dJSONString.append(',"#columnlistKey#":"' & columnlist & '"') />
</cfif>
<cfset dJSONString.append(',"#dataKey#":') />
<!--- Make query a structure of arrays --->
<cfif arguments.queryFormat EQ "query">
<cfset dJSONString.append("{") />
<cfset colPos = 1 />
<cfloop list="#_data.columnlist#" delimiters="," index="column">
<cfif colPos GT 1>
<cfset dJSONString.append(",") />
</cfif>
<cfif arguments.queryKeyCase EQ "lower">
<cfset column = LCase(column) />
</cfif>
<cfset dJSONString.append('"' & column & '":[') />
<cfloop from="1" to="#_data.recordcount#" index="i">
<!--- Get cell value; recurse to get proper format depending on string/number/boolean data type --->
<cfset tempVal = jsonencode( _data[column][i], arguments.queryFormat, arguments.queryKeyCase, arguments.stringNumbers, arguments.formatDates, arguments.columnListFormat ) />
<cfif i GT 1>
<cfset dJSONString.append(",") />
</cfif>
<cfset dJSONString.append(tempVal) />
</cfloop>
<cfset dJSONString.append("]") />
<cfset colPos = colPos + 1 />
</cfloop>
<cfset dJSONString.append("}") />
<!--- Make query an array of structures --->
<cfelse>
<cfset dJSONString.append("[") />
<cfloop query="_data">
<cfif CurrentRow GT 1>
<cfset dJSONString.append(",") />
</cfif>
<cfset dJSONString.append("{") />
<cfset colPos = 1 />
<cfloop list="#columnlist#" delimiters="," index="column">
<cfset tempVal = jsonencode( _data[column][CurrentRow], arguments.queryFormat, arguments.queryKeyCase, arguments.stringNumbers, arguments.formatDates, arguments.columnListFormat ) />
<cfif colPos GT 1>
<cfset dJSONString.append(",") />
</cfif>
<cfif arguments.queryKeyCase EQ "lower">
<cfset column = LCase(column) />
</cfif>
<cfset dJSONString.append('"' & column & '":' & tempVal) />
<cfset colPos = colPos + 1 />
</cfloop>
<cfset dJSONString.append("}") />
</cfloop>
<cfset dJSONString.append("]") />
</cfif>
<!--- Wrap all query data into an object --->
<cfreturn "{" & dJSONString.toString() & "}" />
<!--- UNKNOWN OBJECT TYPE --->
<cfelse>
<cfreturn '"' & "unknown-obj" & '"' />
</cfif>
</cffunction>
<cffunction name="decode" access="remote" returntype="any" output="no"
hint="Converts data frm JSON to CF format">
<cfargument name="data" type="string" required="Yes" />
<!--- DECLARE VARIABLES --->
<cfset var ar = ArrayNew(1) />
<cfset var st = StructNew() />
<cfset var dataType = "" />
<cfset var inQuotes = false />
<cfset var startPos = 1 />
<cfset var nestingLevel = 0 />
<cfset var dataSize = 0 />
<cfset var i = 1 />
<cfset var skipIncrement = false />
<cfset var j = 0 />
<cfset var char = "" />
<cfset var dataStr = "" />
<cfset var structVal = "" />
<cfset var structKey = "" />
<cfset var colonPos = "" />
<cfset var qRows = 0 />
<cfset var qCol = "" />
<cfset var qData = "" />
<cfset var curCharIndex = "" />
<cfset var curChar = "" />
<cfset var result = "" />
<cfset var unescapeVals = "\\,\"",\/,\b,\t,\n,\f,\r" />
<cfset var unescapeToVals = "\,"",/,#Chr(8)#,#Chr(9)#,#Chr(10)#,#Chr(12)#,#Chr(13)#" />
<cfset var unescapeVals2 = '\,",/,b,t,n,f,r' />
<cfset var unescapetoVals2 = '\,",/,#Chr(8)#,#Chr(9)#,#Chr(10)#,#Chr(12)#,#Chr(13)#' />
<cfset var dJSONString = "" />
<cfset var _data = Trim(arguments.data) />
<!--- NUMBER --->
<cfif IsNumeric(_data)>
<cfreturn _data />
<!--- NULL --->
<cfelseif _data EQ "null">
<cfreturn "" />
<!--- BOOLEAN --->
<cfelseif ListFindNoCase("true,false", _data)>
<cfreturn _data />
<!--- EMPTY STRING --->
<cfelseif _data EQ "''" OR _data EQ '""'>
<cfreturn "" />
<!--- STRING --->
<cfelseif ReFind('^"[^\\"]*(?:\\.[^\\"]*)*"$', _data) EQ 1 OR ReFind("^'[^\\']*(?:\\.[^\\']*)*'$", _data) EQ 1>
<cfset _data = mid(_data, 2, Len(_data)-2) />
<!--- If there are any \b, \t, \n, \f, and \r, do extra processing
(required because ReplaceList() won't work with those) --->
<cfif Find("\b", _data) OR Find("\t", _data) OR Find("\n", _data) OR Find("\f", _data) OR Find("\r", _data)>
<cfset curCharIndex = 0 />
<cfset curChar = ""/>
<cfset dJSONString = createObject("java", "java.lang.StringBuffer").init("") />
<cfloop condition="true">
<cfset curCharIndex = curCharIndex + 1 />
<cfif curCharIndex GT len(_data)>
<cfbreak />
<cfelse>
<cfset curChar = mid(_data, curCharIndex, 1) />
<cfif curChar EQ "\">
<cfset curCharIndex = curCharIndex + 1 />
<cfset curChar = mid(_data, curCharIndex,1) />
<cfset pos = listFind(unescapeVals2, curChar) />
<cfif pos>
<cfset dJSONString.append(ListGetAt(unescapetoVals2, pos)) />
<cfelse>
<cfset dJSONString.append("\" & curChar) />
</cfif>
<cfelse>
<cfset dJSONString.append(curChar) />
</cfif>
</cfif>
</cfloop>
<cfreturn dJSONString.toString() />
<cfelse>
<cfreturn ReplaceList(_data, unescapeVals, unescapeToVals) />
</cfif>
<!--- ARRAY, STRUCT, OR QUERY --->
<cfelseif ( Left(_data, 1) EQ "[" AND Right(_data, 1) EQ "]" )
OR ( Left(_data, 1) EQ "{" AND Right(_data, 1) EQ "}" )>
<!--- Store the data type we're dealing with --->
<cfif Left(_data, 1) EQ "[" AND Right(_data, 1) EQ "]">
<cfset dataType = "array" />
<cfelseif ReFindNoCase('^\{"recordcount":[0-9]+,"columnlist":"[^"]+","data":\{("[^"]+":\[[^]]*\],?)+\}\}$', _data, 0) EQ 1>
<cfset dataType = "query" />
<cfelse>
<cfset dataType = "struct" />
</cfif>
<!--- Remove the brackets --->
<cfset _data = Trim( Mid(_data, 2, Len(_data)-2) ) />
<!--- Deal with empty array/struct --->
<cfif Len(_data) EQ 0>
<cfif dataType EQ "array">
<cfreturn ar />
<cfelse>
<cfreturn st />
</cfif>
</cfif>
<!--- Loop through the string characters --->
<cfset dataSize = Len(_data) + 1 />
<cfloop condition="#i# LTE #dataSize#">
<cfset skipIncrement = false />
<!--- Save current character --->
<cfset char = Mid(_data, i, 1) />
<!--- If char is a quote, switch the quote status --->
<cfif char EQ '"'>
<cfset inQuotes = NOT inQuotes />
<!--- If char is escape character, skip the next character --->
<cfelseif char EQ "\" AND inQuotes>
<cfset i = i + 2 />
<cfset skipIncrement = true />
<!--- If char is a comma and is not in quotes, or if end of string, deal with data --->
<cfelseif (char EQ "," AND NOT inQuotes AND nestingLevel EQ 0) OR i EQ Len(_data)+1>
<cfset dataStr = Mid(_data, startPos, i-startPos) />
<!--- If data type is array, append data to the array --->
<cfif dataType EQ "array">
<cfset arrayappend( ar, decode(dataStr) ) />
<!--- If data type is struct or query... --->
<cfelseif dataType EQ "struct" OR dataType EQ "query">
<cfset dataStr = Mid(_data, startPos, i-startPos) />
<cfset colonPos = Find('":', dataStr) />
<cfif colonPos>
<cfset colonPos = colonPos + 1 />
<cfelse>
<cfset colonPos = Find(":", dataStr) />
</cfif>
<cfset structKey = Trim( Mid(dataStr, 1, colonPos-1) ) />
<!--- If needed, remove quotes from keys --->
<cfif Left(structKey, 1) EQ "'" OR Left(structKey, 1) EQ '"'>
<cfset structKey = Mid( structKey, 2, Len(structKey)-2 ) />
</cfif>
<cfset structVal = Mid( dataStr, colonPos+1, Len(dataStr)-colonPos ) />
<!--- If struct, add to the structure --->
<cfif dataType EQ "struct">
<cfset StructInsert( st, structKey, decode(structVal) ) />
<!--- If query, build the query --->
<cfelse>
<cfif structKey EQ "recordcount">
<cfset qRows = decode(structVal) />
<cfelseif structKey EQ "columnlist">
<cfset st = QueryNew( decode(structVal) ) />
<cfif qRows>
<cfset QueryAddRow(st, qRows) />
</cfif>
<cfelseif structKey EQ "data">
<cfset qData = decode(structVal) />
<cfset ar = StructKeyArray(qData) />
<cfloop from="1" to="#ArrayLen(ar)#" index="j">
<cfloop from="1" to="#st.recordcount#" index="qRows">
<cfset qCol = ar[j] />
<cfset QuerySetCell(st, qCol, qData[qCol][qRows], qRows) />
</cfloop>
</cfloop>
</cfif>
</cfif>
</cfif>
<cfset startPos = i + 1 />
<!--- If starting a new array or struct, add to nesting level --->
<cfelseif "{[" CONTAINS char AND NOT inQuotes>
<cfset nestingLevel = nestingLevel + 1 />
<!--- If ending an array or struct, subtract from nesting level --->
<cfelseif "]}" CONTAINS char AND NOT inQuotes>
<cfset nestingLevel = nestingLevel - 1 />
</cfif>
<cfif NOT skipIncrement>
<cfset i = i + 1 />
</cfif>
</cfloop>
<!--- Return appropriate value based on data type --->
<cfif dataType EQ "array">
<cfreturn ar />
<cfelse>
<cfreturn st />
</cfif>
<!--- INVALID JSON --->
<cfelse>
<cfthrow message="Invalid JSON" detail="The document you are trying to decode is not in valid JSON format" />
</cfif>
</cffunction>
<!--- CONVERTS DATA FROM CF TO JSON FORMAT --->
<cffunction name="encode" access="remote" returntype="string" output="No"
hint="Converts data from CF to JSON format">
<cfargument name="data" type="any" required="Yes" />
<cfargument name="queryFormat" type="string" required="No" default="query" /> <!-- query or array -->
<cfargument name="queryKeyCase" type="string" required="No" default="lower" /> <!-- lower or upper -->
<cfargument name="stringNumbers" type="boolean" required="No" default=false >
<cfargument name="formatDates" type="boolean" required="No" default=false >
<cfargument name="columnListFormat" type="string" required="No" default="string" > <!-- string or array -->
<!--- VARIABLE DECLARATION --->
<cfset var jsonString = "" />
<cfset var tempVal = "" />
<cfset var arKeys = "" />
<cfset var colPos = 1 />
<cfset var i = 1 />
<cfset var column = ""/>
<cfset var datakey = ""/>
<cfset var recordcountkey = ""/>
<cfset var columnlist = ""/>
<cfset var columnlistkey = ""/>
<cfset var dJSONString = "" />
<cfset var escapeToVals = "\\,\"",\/,\b,\t,\n,\f,\r" />
<cfset var escapeVals = "\,"",/,#Chr(8)#,#Chr(9)#,#Chr(10)#,#Chr(12)#,#Chr(13)#" />
<cfset var _data = arguments.data />
<!--- BOOLEAN --->
<cfif IsBoolean(_data) AND NOT IsNumeric(_data) AND NOT ListFindNoCase("Yes,No", _data)>
<cfreturn LCase(ToString(_data)) />
<!--- NUMBER --->
<cfelseif NOT stringNumbers AND IsNumeric(_data) AND NOT REFind("^0+[^\.]",_data)>
<cfreturn ToString(_data) />
<!--- DATE --->
<cfelseif IsDate(_data) AND arguments.formatDates>
<cfreturn '"#DateFormat(_data, "medium")# #TimeFormat(_data, "medium")#"' />
<!--- STRING --->
<cfelseif IsSimpleValue(_data)>
<cfreturn '"' & ReplaceList(_data, escapeVals, escapeToVals) & '"' />
<!--- ARRAY --->
<cfelseif IsArray(_data)>
<cfset dJSONString = createObject('java','java.lang.StringBuffer').init("") />
<cfloop from="1" to="#ArrayLen(_data)#" index="i">
<cfset tempVal = encode( _data[i], arguments.queryFormat, arguments.queryKeyCase, arguments.stringNumbers, arguments.formatDates, arguments.columnListFormat ) />
<cfif dJSONString.toString() EQ "">
<cfset dJSONString.append(tempVal) />
<cfelse>
<cfset dJSONString.append("," & tempVal) />
</cfif>
</cfloop>
<cfreturn "[" & dJSONString.toString() & "]" />
<!--- STRUCT --->
<cfelseif IsStruct(_data)>
<cfset dJSONString = createObject('java','java.lang.StringBuffer').init("") />
<cfset arKeys = StructKeyArray(_data) />
<cfloop from="1" to="#ArrayLen(arKeys)#" index="i">
<cfset tempVal = encode( _data[ arKeys[i] ], arguments.queryFormat, arguments.queryKeyCase, arguments.stringNumbers, arguments.formatDates, arguments.columnListFormat ) />
<cfif dJSONString.toString() EQ "">
<cfset dJSONString.append('"' & arKeys[i] & '":' & tempVal) />
<cfelse>
<cfset dJSONString.append("," & '"' & arKeys[i] & '":' & tempVal) />
</cfif>
</cfloop>
<cfreturn "{" & dJSONString.toString() & "}" />
<!--- QUERY --->
<cfelseif IsQuery(_data)>
<cfset dJSONString = createObject('java','java.lang.StringBuffer').init("") />
<!--- Add query meta data --->
<cfif arguments.queryKeyCase EQ "lower">
<cfset recordcountKey = "recordcount" />
<cfset columnlistKey = "columnlist" />
<cfset columnlist = LCase(_data.columnlist) />
<cfset dataKey = "data" />
<cfelse>
<cfset recordcountKey = "RECORDCOUNT" />
<cfset columnlistKey = "COLUMNLIST" />
<cfset columnlist = _data.columnlist />
<cfset dataKey = "data" />
</cfif>
<cfset dJSONString.append('"#recordcountKey#":' & _data.recordcount) />
<cfif arguments.columnListFormat EQ "array">
<cfset columnlist = "[" & ListQualify(columnlist, '"') & "]" />
<cfset dJSONString.append(',"#columnlistKey#":' & columnlist) />
<cfelse>
<cfset dJSONString.append(',"#columnlistKey#":"' & columnlist & '"') />
</cfif>
<cfset dJSONString.append(',"#dataKey#":') />
<!--- Make query a structure of arrays --->
<cfif arguments.queryFormat EQ "query">
<cfset dJSONString.append("{") />
<cfset colPos = 1 />
<cfloop list="#_data.columnlist#" delimiters="," index="column">
<cfif colPos GT 1>
<cfset dJSONString.append(",") />
</cfif>
<cfif arguments.queryKeyCase EQ "lower">
<cfset column = LCase(column) />
</cfif>
<cfset dJSONString.append('"' & column & '":[') />
<cfloop from="1" to="#_data.recordcount#" index="i">
<!--- Get cell value; recurse to get proper format depending on string/number/boolean data type --->
<cfset tempVal = encode( _data[column][i], arguments.queryFormat, arguments.queryKeyCase, arguments.stringNumbers, arguments.formatDates, arguments.columnListFormat ) />
<cfif i GT 1>
<cfset dJSONString.append(",") />
</cfif>
<cfset dJSONString.append(tempVal) />
</cfloop>
<cfset dJSONString.append("]") />
<cfset colPos = colPos + 1 />
</cfloop>
<cfset dJSONString.append("}") />
<!--- Make query an array of structures --->
<cfelse>
<cfset dJSONString.append("[") />
<cfloop query="_data">
<cfif CurrentRow GT 1>
<cfset dJSONString.append(",") />
</cfif>
<cfset dJSONString.append("{") />
<cfset colPos = 1 />
<cfloop list="#columnlist#" delimiters="," index="column">
<cfset tempVal = encode( _data[column][CurrentRow], arguments.queryFormat, arguments.queryKeyCase, arguments.stringNumbers, arguments.formatDates, arguments.columnListFormat ) />
<cfif colPos GT 1>
<cfset dJSONString.append(",") />
</cfif>
<cfif arguments.queryKeyCase EQ "lower">
<cfset column = LCase(column) />
</cfif>
<cfset dJSONString.append('"' & column & '":' & tempVal) />
<cfset colPos = colPos + 1 />
</cfloop>
<cfset dJSONString.append("}") />
</cfloop>
<cfset dJSONString.append("]") />
</cfif>
<!--- Wrap all query data into an object --->
<cfreturn "{" & dJSONString.toString() & "}" />
<!--- UNKNOWN OBJECT TYPE --->
<cfelse>
<cfreturn '"' & "unknown-obj" & '"' />
</cfif>
</cffunction>
<cffunction name="validate" access="remote" output="yes" returntype="boolean"
hint="I validate a JSON document against a JSON schema">
<cfargument name="doc" type="string" required="No" />
<cfargument name="schema" type="string" required="No" />
<cfargument name="errorVar" type="string" required="No" default="jsonSchemaErrors" />
<cfargument name="stopOnError" type="boolean" required="No" default=true />
<!--- These arguments are for internal use only --->
<cfargument name="_doc" type="any" required="No" />
<cfargument name="_schema" type="any" required="No" />
<cfargument name="_item" type="string" required="No" default="root" />
<cfset var schemaRules = "" />
<cfset var jsonDoc = "" />
<cfset var i = 0 />
<cfset var key = "" />
<cfset var isValid = true />
<cfset var msg = "" />
<cfif StructKeyExists(arguments, "doc")>
<cfif FileExists(arguments.doc)>
<cffile action="READ" file="#arguments.doc#" variable="arguments.doc" />
</cfif>
<cfif FileExists(arguments.schema)>
<cffile action="READ" file="#arguments.schema#" variable="arguments.schema" />
</cfif>
<cfset jsonDoc = decode(arguments.doc) />
<cfset schemaRules = decode(arguments.schema) />
<cfset request[arguments.errorVar] = ArrayNew(1) />
<cfelseif StructKeyExists(arguments, "_doc")>
<cfset jsonDoc = arguments._doc />
<cfset schemaRules = arguments._schema />
</cfif>
<!--- See if the document matches the rules from the schema --->
<cfif schemaRules.type EQ "struct">
<cfif NOT IsStruct(jsonDoc)>
<cfset ArrayPrepend(request[arguments.errorVar], "#arguments._item# should be a struct") />
<cfif arguments.stopOnError>
<cfreturn false />
</cfif>
<cfelse>
<!--- If specific keys are set to be required, check if they exist --->
<cfif StructKeyExists(schemaRules, "keys")>
<cfloop from="1" to="#ArrayLen(schemaRules.keys)#" index="i">
<cfif NOT StructKeyExists(jsonDoc, schemaRules.keys[i])>
<cfset ArrayPrepend(request[arguments.errorVar], "#arguments._item# should have a key named #schemaRules.keys[i]#") />
<cfif arguments.stopOnError>
<cfreturn false />
</cfif>
</cfif>
</cfloop>
</cfif>
<!--- Loop over all the keys for the structure and see if they are valid (if items key is specified) by recursing the validate function --->
<cfif StructKeyExists(schemaRules, "items")>
<cfloop collection="#jsonDoc#" item="key">
<cfif StructKeyExists(schemaRules.items, key)>
<cfset isValid = validate(_doc=jsonDoc[key], _schema=schemaRules.items[key], _item="#arguments._item#['#key#']", errorVar=arguments.errorVar, stopOnError=arguments.stopOnError) />
<cfif arguments.stopOnError AND NOT isValid>
<cfreturn false />
</cfif>
</cfif>
</cfloop>
</cfif>
</cfif>
<cfelseif schemaRules.type EQ "array">
<cfif NOT IsArray(jsonDoc)>
<cfset ArrayPrepend(request[arguments.errorVar], "#arguments._item# should be an array") />
<cfif arguments.stopOnError>
<cfreturn false />
</cfif>
<cfelse>
<cfparam name="schemaRules.minlength" default="0" />
<cfparam name="schemaRules.maxlength" default="9999999999" />
<!--- If there are length requirements for the array make sure they are valid --->
<cfif ArrayLen(jsonDoc) LT schemaRules.minlength>
<cfset ArrayPrepend(request[arguments.errorVar], "#arguments._item# is an array that should have at least #schemaRules.minlength# elements") />
<cfif arguments.stopOnError>
<cfreturn false />
</cfif>
<cfelseif ArrayLen(jsonDoc) GT schemaRules.maxlength>
<cfset ArrayPrepend(request[arguments.errorVar], "#arguments._item# is an array that should have at the most #schemaRules.maxlength# elements") />
<cfif arguments.stopOnError>
<cfreturn false />
</cfif>
</cfif>
<!--- Loop over the array elements and if there are rules for the array items recurse to enforce them --->
<cfif StructKeyExists(schemaRules, "items")>
<cfloop from="1" to="#ArrayLen(jsonDoc)#" index="i">
<cfset isValid = validate(_doc=jsonDoc[i], _schema=schemaRules.items, _item="#arguments._item#[#i#]", errorVar=arguments.errorVar, stopOnError=arguments.stopOnError) />
<cfif arguments.stopOnError AND NOT isValid>
<cfreturn false />
</cfif>
</cfloop>
</cfif>
</cfif>
<cfelseif schemaRules.type EQ "number">
<cfif NOT IsNumeric(jsonDoc)>
<cfset ArrayPrepend(request[arguments.errorVar], "#arguments._item# should be numeric") />
<cfif arguments.stopOnError>
<cfreturn false />
</cfif>
<cfelseif StructKeyExists(schemaRules, "min") AND jsonDoc LT schemaRules.min>
<cfset ArrayPrepend(request[arguments.errorVar], "#arguments._item# cannot be a number less than #schemaRules.min#") />
<cfif arguments.stopOnError>
<cfreturn false />
</cfif>
<cfelseif StructKeyExists(schemaRules, "max") AND jsonDoc GT schemaRules.max>
<cfset ArrayPrepend(request[arguments.errorVar], "#arguments._item# cannot be a number greater than #schemaRules.max#") />
<cfif arguments.stopOnError>
<cfreturn false />
</cfif>
</cfif>
<cfelseif schemaRules.type EQ "boolean" AND ( NOT IsBoolean(jsonDoc) OR ListFindNoCase("Yes,No", jsonDoc) OR IsNumeric(jsonDoc) )>
<cfset ArrayPrepend(request[arguments.errorVar], "#arguments._item# should be a boolean") />
<cfif arguments.stopOnError>
<cfreturn false />
</cfif>
<cfelseif schemaRules.type EQ "date">
<cfif NOT IsSimpleValue(jsonDoc) OR NOT IsDate(jsonDoc)
OR ( StructKeyExists(schemaRules, "mask") AND CompareNoCase( jsonDoc, DateFormat(jsonDoc, schemaRules.mask) ) NEQ 0 )>
<cfif StructKeyExists(schemaRules, "mask")>
<cfset msg = " in #schemaRules.mask# format" />
</cfif>
<cfset ArrayPrepend(request[arguments.errorVar], "#arguments._item# should be a date#msg#") />
<cfif arguments.stopOnError>
<cfreturn false />
</cfif>
</cfif>
<cfelseif schemaRules.type EQ "string">
<cfif NOT IsSimpleValue(jsonDoc)>
<cfset ArrayPrepend(request[arguments.errorVar], "#arguments._item# should be a string") />
<cfif arguments.stopOnError>
<cfreturn false />
</cfif>
<cfelseif StructKeyExists(schemaRules, "minlength") AND Len(jsonDoc) LT schemaRules.minlength>
<cfset ArrayPrepend(request[arguments.errorVar], "#arguments._item# should have a minimum length of #schemaRules.minlength#") />
<cfif arguments.stopOnError>
<cfreturn false />
</cfif>
<cfelseif StructKeyExists(schemaRules, "maxlength") AND Len(jsonDoc) GT schemaRules.maxlength>
<cfset ArrayPrepend(request[arguments.errorVar], "#arguments._item# should have a maximum length of #schemaRules.maxlength#") />
<cfif arguments.stopOnError>
<cfreturn false />
</cfif>
</cfif>
</cfif>
<cfif ArrayLen(request[arguments.errorVar])>
<cfreturn false />
<cfelse>
<cfreturn true />
</cfif>
</cffunction>
</cfcomponent>