2

ですから、私は非常に苛立たしい問題を経験しています。Coldfusionオブジェクトのフィルタリングに使用される基準を送信するAJAX呼び出しを(jquery.post()を介して)行っています。

処理は非常に簡単です。最初に、特定のフィルターが渡されたかどうかを確認するためのチェックが実行されます。フィルターが存在する場合、セッションスコープ内のオブジェクトがループされ、オブジェクト要素の1つの値がフィルターのリスト内の項目と一致する場合値の場合、そのオブジェクトは配列に追加されます。定義されたすべてのフィルタータイプに対してこのプロセスが完了すると、一致するオブジェクトの配列が結果オブジェクト(obj.results)に格納され、serializeJSON関数に渡され、最終的にクライアントに返されます。

残念ながら、複数のフィルターが使用されている場合、ループが途中で終了したように見え、一致する結果よりも少ない結果が返されます。以下に含まれている2つのフィルターのいずれか1つだけを処理すると、期待どおりの結果が得られます。同様に、以下の各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]

サーバー上で発生している2つのループのある種の非同期処理が必要であるか、ループが終了する前に何かがタイムアウトしているように感じます。

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

関数から返す前に絶対にシリアル化する必要がある場合は、オブジェクト全体ではなく文字列を返す配列変数に追加し、この関数を呼び出す範囲外のコードをリファクタリングする必要があります。

出典:serializeJSONの問題-埋め込みオブジェクトを切り捨てます

于 2012-08-10T20:45:11.880 に答える