Coldfusion:api 调用数组和结构时的嵌套循环

Coldfusion: Nested Loop on api call Array & Struct

我的函数调用 SendGrid API。它return是一个数组+结构。我正在为 return CFQuery 数据集编写一个函数。

目标 我想将反序列化的数据对象传递给我的函数并获取查询数据集。

这是我的工作代码和输出:

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

我的代码:

 <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>

结果:

当我在函数中添加这一行时

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

发生错误:

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

** 完整代码**

    <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> 

ERROR

您的 UDF arrayit 接受类型为 array 的参数,但是当该条件为真时,将传递 struct,因此出现错误。 即,

<cfif isStruct(stru[S])>

    <!--- This means stru[S] is a struct  --->
    <cfset variables.ddata = arrayit(arrobj = stru[S])>
    <!--- arrObj should be of type 'array' --->
</cfif>

所以,应该是:

<cfif isStruct(stru[S])>
    <cfset variables.ddata = structit(structobj = stru[S])>
</cfif>

但是,这种情况下的错误将与您添加的不同。

此外,

  • StructInsert() 采用可选参数 allowoverwrite 默认情况下为 false 并且根据文档:

if key exists and allowoverwrite = "False", ColdFusion throws an exception.

我刚刚做到了! :) 只是想与大家分享我的项目也希望它能帮助其他人...

请求如果你们发现任何我可以改进的地方请分享。

特别感谢您对我的回复 post。 @初学者和@Leigh

API调用JsonReturn: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) />

氟氯化碳: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">

妈妈! ....