Coldfusion:对象数组的奇怪行为

时间:2012-08-10 19:02:33

标签: arrays object loops coldfusion

所以,我遇到了一个非常令人沮丧的问题。我正在进行AJAX调用(通过jquery.post()),该调用发送用于过滤Coldfusion对象的条件。

处理非常简单。首先,执行检查以查看是否已传入某些过滤器。如果存在过滤器,则会话范围中的对象循环通过,并且如果其中一个对象元素的值与过滤器列表中的任何项匹配值,该对象被添加到数组中。对所有已定义的过滤器类型完成此过程后,匹配对象的数组将存储在结果对象(obj.results)中,传递给serializeJSON函数,然后最终返回给客户端。

不幸的是,如果有多个过滤器正在运行,则看起来好像过早退出循环,导致返回的结果少于匹配。如果我只处理下面包含的两个过滤器中的一个,我会得到完整的预期结果。同样,如果在下面的每个arrayappend()调用中,我将s [i]更改为s [i] .name(因此,附加字符串而不是对象),将为每个过滤器返回预期的结果数。

这是使用s [i]的代码:

<cffunction name="filterObj" access="public" returntype="any">
    <cfargument name="filterParams" type="struct" required="yes">
    <cfset var s = session.a> <!--- session.a IS AN ARRAY OF CF OBJECTS --->
    <cfset filteredResults = {}>
    <cfset filteredResults.eligibilities = []>
    <cfset filteredResults.agencies = []>
    <cfif isdefined("arguments.filterParams.agency")>
        <cfloop from="1" to="#arraylen(s)#" index="i">
            <cfif structkeyexists(s[i],"agency") and
                listfindnocase(arguments.filterParams["agency"],s[i].agency["name"])>
                    <cfset arrayappend(filteredResults.agencies, s[i])>
            </cfif>
        </cfloop>
    </cfif>
    <cfif isdefined("arguments.filterParams.eligibility")>
        <cfloop from="1" to="#arraylen(s)#" index="i">
            <cfif structkeyexists(s[i],"el")>
                <cfloop from="1" to="#arraylen(s[i].eligibility)#" index="e">
                    <cfif listfindnocase(arguments.filterParams["eligibility"],s[i].eligibility[e].type)>
                        <cfset arrayappend(filteredResults.eligibilities, s[i])>
                    </cfif>
                </cfloop>
            </cfif>
        </cfloop>
    </cfif>
    <cfset obj.results = filteredResults>
    <cfset obj = serializeJSON(obj)>
    <cfreturn obj>
</cffunction>

以下是使用s [i]

的未展开的console.logged结果
RESULTS: Object
  AGENCIES: Array[5]
  ELIGIBILITIES: Array[5]

这是使用s [i] .name

的代码
<cffunction name="filterObj" access="public" returntype="any">
    <cfargument name="filterParams" type="struct" required="yes">
    <cfset var s = session.a> <!--- session.a IS AN ARRAY OF CF OBJECTS --->
    <cfset filteredResults = {}>
    <cfset filteredResults.eligibilities = []>
    <cfset filteredResults.agencies = []>
    <cfif isdefined("arguments.filterParams.agency")>
        <cfloop from="1" to="#arraylen(s)#" index="i">
            <cfif structkeyexists(s[i],"agency") and
                listfindnocase(arguments.filterParams["agency"],s[i].agency["name"])>
                    <cfset arrayappend(filteredResults.agencies, s[i].name)>
            </cfif>
        </cfloop>
    </cfif>
    <cfif isdefined("arguments.filterParams.eligibility")>
        <cfloop from="1" to="#arraylen(s)#" index="i">
            <cfif structkeyexists(s[i],"el")>
                <cfloop from="1" to="#arraylen(s[i].eligibility)#" index="e">
                    <cfif listfindnocase(arguments.filterParams["eligibility"],s[i].eligibility[e].type)>
                        <cfset arrayappend(filteredResults.eligibilities, s[i].name)>
                    </cfif>
                </cfloop>
            </cfif>
        </cfloop>
    </cfif>
    <cfset obj.results = filteredResults>
    <cfset obj = serializeJSON(obj)>
    <cfreturn obj>
</cffunction>

以下是使用s [i] .name

的未展开的console.logged结果
RESULTS: Object
  AGENCIES: Array[10]
  ELIGIBILITIES: Array[6]

我觉得必须对服务器上发生的两个循环进行某种异步处理,或者在循环完成之前某些东西超时。

1 个答案:

答案 0 :(得分:3)

在某些版本的CF9中存在已知问题,以及CF10,关于对象数组的序列化;通过将对象本身附加到return var而不是所述对象的基于字符串的键,你偶然发现了这个bug。

通过这个简单的脚本可以重现错误:

<cfset obj = ArrayNew(1) />

<cfset obj[1] = StructNew() />
<cfset obj[1].name = "Kate" />
<cfset obj[2] = StructNew() />
<cfset obj[2].name = "Ted" />
<cfset obj[3] = StructNew() />
<cfset obj[3].name = "Phil" />

<cfset data = ArrayNew(1) />

<cfloop from="1" to="#ArrayLen(obj)#" index="i">
    <cfset ArrayAppend(data, obj[i]) />
</cfloop>

<cfdump var=#data#>

<cfloop from="1" to="#ArrayLen(obj)#" index="i">
    <cfset ArrayAppend(data, obj[i]) />
</cfloop>

<cfdump var=#data#>

<cfoutput>#ArrayLen(data)#</cfoutput>
<cfset json = SerializeJSON(data) />

<cfdump var=#json#>

<cfset converted = DeserializeJSON(json) />
<cfoutput>#ArrayLen(converted)#</cfoutput>

预期的结果是最终的反序列化数组长度为6个元素,因为它是预序列化的。但是,实际结果是3。

坚持将字符串而不是整个对象附加到要返回的数组var中,如果绝对必须在从函数返回之前对其进行序列化,并重构调用此函数的异常代码。

消息来源:Problem with serializeJSON -- truncates embedded objects