Flatten any variable type in ColdFusion
I created a function that flattens different types of complex (nested) variables, like structures, arrays and queries. The function is based on the flattenStruct (https://cflib.org/udf/flattenStruct) UDF by Tom de Manincor.
<cffunction name="flattenAnything" access="public" output="true" returntype="struct" hint="Flattens structures, arrays and queries">
<cfargument name="in" type="any" required="true" hint="struct, array or query to flatten">
<cfargument name="delimiter" required="false" type="string" default="." />
<cfargument name="prefix_string" type="string" default="" required="false" hint="result struct, returned at the end">
<cfargument name="out" type="struct" default="#StructNew()#" required="false" hint=" used in the processing, stores the preceding struct names in the current branch, ends in a delimeter">
<Cfset var local = {}>
<Cfif isStruct(in)>
<cfset local.keyArray = StructKeyArray(in)>
<cfloop from=1 to=#arrayLen(local.keyArray)# index="local.x">
<Cfif isStruct(in[local.keyArray[x]])>
<cfset out = flattenAnything(in[local.keyArray[x]],delimiter, prefix_string & local.keyArray[x] & delimiter,out)>
<Cfelseif isArray(in[local.keyArray[x]])>
<cfset out = flattenAnything(in[local.keyArray[x]],delimiter, prefix_string & local.keyArray[x] & delimiter,out)>
<Cfelseif isQuery(in[local.keyArray[x]])>
<cfset out = flattenAnything(in[local.keyArray[x]],delimiter, prefix_string & local.keyArray[x] & delimiter,out)>
<cfelse>
<cfset out[prefix_string & local.keyArray[local.x]] = in[local.keyArray[local.x]]>
</cfif>
</cfloop>
<Cfelseif isArray(in)>
<cfloop from=1 to=#arrayLen(in)# index="local.y">
<cfset out = flattenAnything({"#local.y#":in[local.y]},delimiter, prefix_string,out)>
</cfloop>
<cfelseif isQuery(in)>
<Cfset local.q.columnLabels = in.columnList>
<Cfset local.q.array = []>
<cfloop from=1 to=#in.recordcount# index="local.y">
<Cfloop list="#local.q.columnLabels#" item="local.q.columnName">
<cfset local.q.array[local.y][local.q.columnName] = in[local.q.columnName][local.y] >
</cfloop>
</cfloop>
<Cfset local.q.prefix_string = prefix_string>
<cfif local.q.prefix_string eq delimiter><Cfset local.q.prefix_string = ""></cfif>
<cfset out = flattenAnything(local.q.array,delimiter, local.q.prefix_string,out)>
<Cfelseif isSimpleValue(in)>
<Cfset out = {"SimpleValue":in}>
<Cfelse>
<Cfset out = {"UnkownVariable":in}>
</cfif>
<cfreturn out>
</cffunction>
Below a simple example:
<cfscript>
str = structNew();
str.query = people = queryNew("id, firstName, lastName, email, country, ip_address","integer, varchar, varchar, varchar, varchar, varchar",[
{ "id": 1, "firstName": "John", "lastName": "Do", "email": "some@one.com", "country": "Poland", "ip_address": "10.0.0.1"},
{ "id": 2, "firstName": "Jane", "lastName": "Do", "email": "mail@address.org", "country": "Iceland", "ip_address": "10.0.0.2"}
]);
str.alpha = structNew();
str.alpha.alpha = true;
str.alpha.beta = true;
str.alpha.gamma = true;
str.alpha.delta = structNew();
str.alpha.delta.alpha = 'test';
str.alpha.epsilon = ['alpha','beta','gamma',{"alpha":"1","beta":[1,2,3,4]}];
str.alpha.zeta = [1,2,3,4];
str.alpha.eta = [[1,2,3,4],['a','b','c','d']];
</cfscript>
<cfdump var="#flattenAnything(str)#">
admin
0