Creating a function in Coldfusion to dynamically convert a multidimensional array to a query object

Viewed 77

The problem I'm running into is the API I'm using for this particular project uses periods in the keys which is not allowed in query column names. So I need to figure out a way to rename the array keys to remove the periods (or replace them with an underscore). Here is the code I have so far, which is working, but throws an error when hitting the "accumulator.addRow" line. The error being that periods aren't allowed in column names.

<cfset varResults = '[{"roW_NUMBER":1,"membership.Individual.LocalID":999,"membership.Individual.FirstName":"AA","membership.Individual.LastName":"AA","membership.Individual.Company":null,"membership.Individual.Work_Address_Line1":"aaaa","membership.Individual.Work_Address_Line2":null,"membership.Individual.Work_Address_City":"Alexandria","membership.Individual.Work_Address_State":"VA","membership.Individual.Work_Address_PostalCode":"9999-2518","membership.Individual.Work_Address_CountryName":"UNITED STATES","membership.Individual.EmailAddress":"AA.AA@gmail.com","membership.Type.Name":"Regular","membership.JoinDate":"2009-05-01T00:00:00","membership.ExpirationDate":"2023-04-30T00:00:00","membership.Individual.FellowElectDate__c":null,"chapter.Name":"DDDD","id":"0e04bc98-0074-cc58-bf6a-0b438d800e7d"},{"roW_NUMBER":2,"membership.Individual.LocalID":9998,"membership.Individual.FirstName":"AA","membership.Individual.LastName":"AA","membership.Individual.Company":null,"membership.Individual.Work_Address_Line1":"ASASASAAASAS","membership.Individual.Work_Address_Line2":null,"membership.Individual.Work_Address_City":"Washington","membership.Individual.Work_Address_State":"DC","membership.Individual.Work_Address_PostalCode":"9999","membership.Individual.Work_Address_CountryName":"UNITED STATES","membership.Individual.EmailAddress":"ASASASA@gmail.com","membership.Type.Name":"Regular","membership.JoinDate":"2020-01-01T00:00:00","membership.ExpirationDate":"2022-12-31T00:00:00","membership.Individual.FellowElectDate__c":null,"chapter.Name":"DDDD","id":"0e04bc98-0074-c1ae-f171-0b438d800e7c"}]'>
<cfscript>
    function arrayToQuery(varChapterRoster) {
        return varChapterRoster.reduce(function(accumulator, element) {
            element.each(function(key) {
                if (!accumulator.keyExists(replace(key,".","_","all"))) {
                    accumulator.addColumn(replace(key,".","_","all"), []);
                }
            });
            //writeDump(element);
            accumulator.addRow(element);
            return accumulator;
        }, QueryNew(""));
    }
    // writeDump(varChapterRoster);
    writeDump(arrayToQuery(varChapterRoster));
</cfscript>

Specific error: Column names must be valid variable names. They must start with a letter and can only include letters, numbers, and underscores.

I got past the "keyexists" and "addcolumn" lines by using the replace function, but replace won't work on "element" (throws an error) on the addRow line.

Changing tactics, here is a CFFiddle with some dummy data in it of the method I'm trying now. I think it is more straight forward, but getting another error that I bet is related to the periods again.

1 Answers
<cfset varResults = '[{"roW_NUMBER":1,"membership.Individual.LocalID":999,"membership.Individual.FirstName":"AA","membership.Individual.LastName":"AA","membership.Individual.Company":null,"membership.Individual.Work_Address_Line1":"aaaa","membership.Individual.Work_Address_Line2":null,"membership.Individual.Work_Address_City":"Alexandria","membership.Individual.Work_Address_State":"VA","membership.Individual.Work_Address_PostalCode":"9999-2518","membership.Individual.Work_Address_CountryName":"UNITED STATES","membership.Individual.EmailAddress":"AA.AA@gmail.com","membership.Type.Name":"Regular","membership.JoinDate":"2009-05-01T00:00:00","membership.ExpirationDate":"2023-04-30T00:00:00","membership.Individual.FellowElectDate__c":null,"chapter.Name":"DDDD","id":"0e04bc98-0074-cc58-bf6a-0b438d800e7d"},{"roW_NUMBER":2,"membership.Individual.LocalID":9998,"membership.Individual.FirstName":"AA","membership.Individual.LastName":"AA","membership.Individual.Company":null,"membership.Individual.Work_Address_Line1":"ASASASAAASAS","membership.Individual.Work_Address_Line2":null,"membership.Individual.Work_Address_City":"Washington","membership.Individual.Work_Address_State":"DC","membership.Individual.Work_Address_PostalCode":"9999","membership.Individual.Work_Address_CountryName":"UNITED STATES","membership.Individual.EmailAddress":"ASASASA@gmail.com","membership.Type.Name":"Regular","membership.JoinDate":"2020-01-01T00:00:00","membership.ExpirationDate":"2022-12-31T00:00:00","membership.Individual.FellowElectDate__c":null,"chapter.Name":"DDDD","id":"0e04bc98-0074-c1ae-f171-0b438d800e7c"}]'>
<cfset varResults = replace(varResults,":null",':""',"All")>
<cfset varResults = replace(varResults,"T00:00:00","","All")>
<cfset varResults = deserializeJSON(varResults)>

Answer based on original post. Demo

<cfscript>
    function arrayToQuery(varChapterRoster) {
        if(varChapterRoster.len() == 0){
            return QueryNew('');
        }
        return varChapterRoster.reduce(function(accumulator, element) {
            Row = QueryAddRow(accumulator);
            element.each(function(key) {
                QuerySetCell( accumulator , replace(key,".","_","all") , element[key] , Row );
            });
            return accumulator;
        }, QueryNew(replace(StructKeyList(varResults[1]),".","_","all")));
    }
    // writeDump(varChapterRoster);
    writeDump(arrayToQuery(varResults));
</cfscript>

Answer based on your cffiddle. Demo

<cfif NOT ArrayLen(varResults)>
    <cfthrow message="No data" />
</cfif>

<cfset Q = QueryNew( replace(StructKeyList(varResults[1]),".","_","all") ) />

<cfloop index="item" array="#varResults#">
    <cfset Row = QueryAddRow(Q) />
    <cfloop item="ColName" collection="#item#" >
        <cfset QuerySetCell( Q , replace(ColName,".","_","all") , item[ColName] , Row ) />
    </cfloop>
</cfloop>

<cfdump var=#Q# />
Related