2

所以,我遇到了一个非常令人沮丧的问题。我正在进行 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]

我觉得服务器上必须对两个循环进行某种异步处理,或者在循环完成之前某些事情已经超时。

4

1 回答 1

3

在某些版本的 CF9 和 CF10 中存在一个关于对象数组序列化的已知问题;您通过将对象本身附加到返回变量而不是所述对象的基于字符串的键而偶然发现了这个错误。

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

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

来源:serializeJSON 的问题——截断嵌入的对象

于 2012-08-10T20:45:11.880 回答