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)>
              	<cfset out[prefix_string & local.keyArray[local.x]] = in[local.keyArray[local.x]]>
	<Cfelseif isArray(in)>
        <cfloop from=1 to=#arrayLen(in)# index="local.y">
            <cfset out = flattenAnything({"#local.y#":in[local.y]},delimiter, prefix_string,out)>
	<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] >
		<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}>
	    <Cfset out = {"UnkownVariable":in}>

    <cfreturn out>

Below a simple example:

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": ""}, 
	{  "id": 2,  "firstName": "Jane",  "lastName": "Do",  "email": "mail@address.org",  "country": "Iceland",  "ip_address": ""}
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']];
<cfdump var="#flattenAnything(str)#">


Leave a Reply

Your email address will not be published. Required fields are marked *