Search code examples
coldfusionsendgridcoldfusion-10cfmlcoldfusion-11

Coldfusion: Nested Loop on api call Array & Struct


My function calls the SendGrid API. It returns an Array + structure. I'm writing a function to return a CFQuery dataset.

Goal I want to pass a deserialized data object to my function and get a query dataset.

Here is my working code and the output:

<cfparam name="variables.ddata" default="#structnew()#">
<!--- API Call Code here --->
<cfset arr = DESerializeJSON(returnStruct.Filecontent) />
<cfdump var="#arr#">

CFdump on call

My code:

 <cfset arrayit(arrobj= arr) >
 <cfdump var="#variables.ddata#" >
 <cffunction name="arrayit" access="public" returntype="void">
    <cfargument name="arrobj" type="array"  required="yes">
    <cfset var arr=arguments.arrobj />
    <cfloop from="1" to =   "#arrayLen(arr)#" index="i">
       <cfif isValid("string", arr[i])>
          <cfset StructInsert(variables.ddata, i, arr[i]) />
       </cfif>
       <cfif isstruct(arr[i])>
          <cfset structit(structobj = arr[i]) />
       </cfif>
    </cfloop>
</cffunction>

<cffunction name="structit" access="public" returntype="void" output="yes">
   <cfargument name="structobj" type="any" required="yes">
   <cfset  stru = arguments.structobj />
   <cfloop collection="#stru#" item="S"> 
       <cfif isValid("string", stru[S])>
          <cfset StructInsert( variables.ddata, S, stru[S]) />
       </cfif>
       <cfif isarray(stru[S])>
           <cfset arrayit(arrobj = stru[S]) >
       </cfif>
   </cfloop>
</cffunction>

Result:

Result

When I add this line in my function

<cfif isstruct(stru[S])>
    <cfset variables.ddata   =  arrayit(arrobj = stru[S]) />
</cfif>

An error occurs:

Element type is undefined in a CFML structure referenced as part of an expression.
The error occurred on line 71.

** Full Code**

    <cfsavecontent variable="returnStruct.Filecontent">
[{"date":"2016-04-05","stats":[{"type":"category","name":"5","metrics":{"blocks":1,"bounce_drops":0,"bounces":9,"clicks":4,"deferred":1,"delivered":1,"invalid_emails":8,"opens":4,"processed":1,"requests":1,"spam_report_drops":0,"spam_reports":1,"unique_clicks":3,"unique_opens":3,"unsubscribe_drops":0,"unsubscribes":9}}]}]
</cfsavecontent>

<cfset arr = DESerializeJSON(returnStruct.Filecontent) />

<cfloop from="1" to="#arrayLen(arr)#" index="i">
   <cfif isValid("string", arr[i])>
        <cfset StructInsert(variables.ddata, i, arr[i],true ) />
   </cfif>

   <cfif isstruct(arr[i])>
        <cfsavecontent variable="rr">
            <cfdump var="#arr[i]#"  label="Line 48 ERROR" >
        </cfsavecontent>
        <cfset NotifyErrorAdmin(emailBody = "#rr#"  ,emailsubject = "Line 48") />
        <cfset structit(structobj = arr[i]) />
   </cfif>
      <cfif isarray(arr[i])>
        <cfsavecontent variable="rr">
            <cfdump var="#arr[i]#"  label="Line 54 ERROR" >
        </cfsavecontent>
        <cfset NotifyErrorAdmin(emailBody = "#rr#"  ,emailsubject = "Line 54") />
        <cfset arrayit(arrobj = arr[i]) >
    </cfif>
</cfloop>
</cffunction> 

<cffunction name        =   "structit" access="public" returntype="void" output="yes">
<cfargument name        =   "structobj" type="any" required="yes">
<cfset  stru            =   arguments.structobj />

<cfloop collection="#stru#" item="S"> 
    <cfif isValid("string", stru[S])>
         <cfset StructInsert( variables.ddata, S, stru[S],true) />
    </cfif>
    <cfif isarray(stru[S])>
        <cfsavecontent variable="rr">
            <cfdump var="#stru[S]#"  label="Line 86 ERROR" >
        </cfsavecontent>
        <cfset NotifyErrorAdmin(emailBody = "#rr#"  ,emailsubject = "Line 87") />
        <cfset arrayit(arrobj = stru[S]) >
    </cfif>
 <cfif isstruct(stru[S])>
        <cfsavecontent variable="rr">
            <cfdump var="#stru[S]#"  label="Line 97 ERROR" >
        </cfsavecontent>
        <cfset NotifyErrorAdmin(emailBody = "#rr#"  ,emailsubject = "Line 97") />
        <cfset structit(structobj = stru[S]) />
   </cfif>
</cfloop>
</cffunction> 

ERRORSg3Sg4sg5sg1err


Solution

  • I just did it! :) just wanted to share my project with you guys also hope it will help someone else also...

    Request if you guys find anything you feel I can improve please share.

    Special Thanks for response on my post. @Beginner & @Leigh

    API Call Json Return: 1

        <cfsavecontent variable="returnStruct.Filecontent">
    [{"date":"2016-04-05","stats":[{"type":"category","name":"5","metrics":{"blocks":1,"bounce_drops":0,"bounces":9,"clicks":4,"deferred":1,"delivered":1,"invalid_emails":8,"opens":4,"processed":1,"requests":1,"spam_report_drops":0,"spam_reports":1,"unique_clicks":3,"unique_opens":3,"unsubscribe_drops":0,"unsubscribes":9}}]}]
    </cfsavecontent>
    
    <cfset arr = DESerializeJSON(returnStruct.Filecontent) />
    

    CFC : 2

        <cfcomponent>
    <cfparam name="variables.qryclsvar" default=""  type="any"/> 
    <cfparam name="variables.qryclsvarfg" default="true"  type="any"/> 
    
    <cffunction name="APItoquery" access="public" returntype="any">
    <cfargument name        = "APIobj"          type="any"  required="yes">
    <cfset var vAPIobj      = arguments.APIobj />
    <cfset var APIDATA      = structnew() />
    <cfset var APIDATAqr        = "" />
    <cftry>
        <cfloop from="1" to="#arrayLen(vAPIobj)#" index="jj">
             <cfif  isarray(vAPIobj[jj])>
                <cfset APIDATA =  arrayit(structobj = vAPIobj[jj] ,datastruct = APIDATA) />
             </cfif>
              <cfif isstruct(vAPIobj[jj])>
                <cfset APIDATA =  structit(structobj = vAPIobj[jj],datastruct = APIDATA) />
           </cfif>
    
            <cfif NOT StructIsEmpty(APIDATA)>  
                <!--- Add in query object --->
                <cfset APIDATAqr = structtoquery(structobj= APIDATA) />
            <cfelse>
                <cfset APIDATAqr ="NO Data Found!" />
            </cfif>
        </cfloop>
    
     <cfcatch>
        <cfdump var="#cfcatch#" label="APItoquery">
     </cfcatch>
     </cftry>
    <cfreturn APIDATAqr>
    </cffunction>
    
    
    
    <cffunction name        =   "arrayit"           access="public" returntype="any">
    <cfargument name        =   "arrobj"            type="any"  required="yes">
    <cfargument name        =   "datastruct"        type="any"  required="yes" >
    <cfset  var arr         =   arguments.arrobj />
    <cfset  var arrdata     =   arguments.datastruct />
    <cftry>
    <cfloop from="1" to="#arrayLen(arr)#" index="i">
            <cfif ArrayContains(arr, i) >
                <cfset StructInsert(arrdata, i, arr[i],true ) />
    
            </cfif>
            <cfif  isarray(arr[i])>
                <cfset arrdata  =   arrayit(arrobj = arr[i] ,datastruct = arrdata) >
            </cfif>
            <cfif isstruct(arr[i]) >
                <cfset stdata   =    structit(structobj = arr[i],datastruct = arrdata) />
           </cfif>
    </cfloop>
     <cfcatch>
        <cfdump var="#cfcatch#" label="arrayit">
     </cfcatch>
     </cftry>
     <cfreturn arrdata>
    </cffunction> 
    
    
    <cffunction name        =   "structit"          access="public" returntype="any" output="yes">
    <cfargument name        =   "structobj"         type="any" required="yes">
    <cfargument name        =   "datastruct"        type="any"  required="yes">
    <cfset  var stru        =   arguments.structobj />
    <cfset  var stdata      =   arguments.datastruct />
    <cftry>
        <cfloop collection="#stru#" item="S"> 
            <cfif  isarray(stru[S])>
                <cfset stdata   =   arrayit(arrobj = stru[S] ,datastruct = stdata) >
             <cfelseif isstruct(stru[S]) >
                <cfset stdata   =    structit(structobj = stru[S],datastruct = stdata) />
             <cfelse>
                <cfset StructInsert( stdata, S, stru[S],true) />
    
            </cfif>
        </cfloop>
     <cfcatch>
        <cfdump var="#cfcatch#" label="structit">
     </cfcatch>
     </cftry>
     <cfreturn stdata>
    </cffunction> 
    
    <cffunction name        =   "structtoquery"             access="public" returntype="any" output="yes">
    <cfargument name        =   "structobj"             type="any" required="yes">
    <cfset  var vstructobj      =   arguments.structobj />
    <cfset var cols     = StructKeyList(vstructobj)>
    <cfset var colstyp = "">
            <cftry>
                <cfif variables.qryclsvarfg EQ true>
                    <cfloop from="1" to="#listlen(cols,',')#" index="L">
                        <cfset colstyp = ListAppend(colstyp,"VarChar",",")>
                    </cfloop>
                    <!--- Create a new query. --->
                    <cfset variables.qryclsvar = queryNew(
                                            '#cols#',
                                            '#colstyp#'
                                            )>
                <cfset variables.qryclsvarfg = false>
                </cfif>   
                <cfset QueryAddRow(variables.qryclsvar, 1)>
                 <cfloop collection="#vstructobj#" item="sd">
                    <cfset QuerySetCell(variables.qryclsvar,    "#sd#", vstructobj[sd])>
                 </cfloop>
    
             <cfcatch>
                <cfdump var="#cfcatch#" label="structit">
             </cfcatch>
             </cftry>
     <cfreturn variables.qryclsvar>
    </cffunction> 
    </cfcomponent>
    

    CFM : 3

    <cfset sgObj =  createobject("component","cfc.mycfc") />
    <cfset mystruct = sgObj.APItoquery(APIobj= arr1) >
    <cfdump var="#mystruct#"  label="mystruct">
    

    MA ! ....