【问题标题】:Coldfusion: Odd Behavior with Array of ObjectsColdfusion:对象数组的奇怪行为
【发布时间】:2012-08-10 19:02:33
【问题描述】:

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

处理非常简单。首先,执行检查以查看是否已传入某些过滤器。如果存在过滤器,则循环遍历会话范围内的对象,如果其中一个对象元素的值与过滤器列表中的任何项目匹配值,该对象被添加到数组中。一旦对所有定义的过滤器类型完成此过程,匹配对象的数组将存储在结果对象 (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) 此函数是否驻留在 CFC 中? 2)你如何调用该方法? (CFINVOKE 或通过 CreateObject,稍后调用该方法),以及 3)您是否将此 CFC 存储在共享范围(即 APPLICATION)中?
  • 我要尝试的第一件事是确保您对所有循环索引和临时变量使用 VAR 范围。
  • 嗨,Shawn,1) 该函数确实驻留在 CFC 中。 2) 通过 调用它 3) CFC 未存储在共享范围内
  • 我仍然需要知道 #2 和 #3 才能明确回答。
  • 是的,抱歉,我敲的太早了。

标签: arrays object loops coldfusion


【解决方案1】:

在某些版本的 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。

来源:Problem with serializeJSON -- truncates embedded objects

【讨论】:

  • 非常感谢。我又恢复了理智!我已联系 IT 以查看他们是否会安装此修补程序。将其作为 JSON 字符串处理是可行的,但将是一项相当大的工作(需要循环的大量嵌套信息)。
  • 没关系:修复程序。我刚刚有机会阅读了@Shawn 发布的 Adob​​e 论坛帖子上的用户 cmets,它似乎在修补程序 2 中仍然存在。所以,我去了 Adob​​e BugBase 并投票支持这个错误:bugbase.adobe.com/index.cfm?event=bug&id=3042650
  • 仅供参考 - 此线程中讨论的错误显然已在 CF10 中修复。见这里:bugbase.adobe.com/index.cfm?event=bug&id=3175667我们仍在运行 9,所以我无法直接确认...
猜你喜欢
  • 2017-12-02
  • 1970-01-01
  • 2021-10-27
  • 1970-01-01
  • 2010-12-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-30
相关资源
最近更新 更多