【发布时间】:2014-04-14 14:14:56
【问题描述】:
我最近将一个系统从 CF8 升级到了 CF10,并且有一个错误,我在追踪时遇到了问题。它与一个远程 API 调用有关,该调用返回一个 JSON 字符串,然后将该字符串转换为查询对象。这就是我遇到错误的地方:
元素 [n] 在类型为coldfusion.runtime.Array 的Java 对象中未定义。问题在于将字符串转换为查询的函数。
<cffunction name="CFjsonToQuery" access="public" returntype="query" output="no">
<cfargument name="cfData" required="yes" type="struct"/>
<cfset var LOCAL = {}/>
<cfset LOCAL.tmpQry = QueryNew( ArrayToList(ARGUMENTS.cfData.Data.COLUMNS) ) />
<cfloop index = "i" from = "1" to = "#ArrayLen(ARGUMENTS.cfData.Data.DATA)#">
<cfset LOCAL.Row = QueryAddRow(LOCAL.tmpQry) />
<cfloop index="k" from="1" to="#ArrayLen(ARGUMENTS.cfData.Data.DATA[i])#">
<cfset LOCAL.colName = ARGUMENTS.cfData.Data.COLUMNS[K]/>
<cfset QuerySetCell(LOCAL.tmpQry,LOCAL.colName,ARGUMENTS.cfData.Data.DATA[i][k],LOCAL.Row)/>
</cfloop>
</cfloop>
<cfreturn LOCAL.tmpQry/>
</cffunction>
在 JSON 返回“null”的任何地方(即“...”、“19107-3609”、null、null、null、“...”)都会引发错误。我尝试使用 isNull 检查它在 cfloop 中是否为空:
<cfif isNull(ARGUMENTS.cfData.Data.DATA[i][k])>
<cfset ARGUMENTS.cfData.Data.DATA[i][k] = 'I AM NULL'/>
</cfif>
编辑 - 这是一个简化的例子 - 问题是我相信较新的 deserializeJson() 的工作方式:
<cfset jstr = '{"SUCCESS":true,"ERRORS":[],"DATA":{"COLUMNS":["ID","FNAME","LNAME"],"DATA":[[390132,"steve",null]]}}'/>
<cfset cfData = deserializeJson(jstr) />
<cfloop index = "i" from = "1" to = "#ArrayLen(cfData.Data.DATA)#">
<cfset Row = QueryAddRow(tmpQry) />
<cfloop index="k" from="1" to="#ArrayLen(cfData.Data.DATA[i])#">
<cfset colName = cfData.Data.COLUMNS[K]/>
<cfset QuerySetCell(tmpQry,colName,cfData.Data.DATA[i][k],Row)/>
</cfloop>
</cfloop>
我已经对空字符串、isNull 等进行了各种测试,但我仍然不确定如果 deserializejson 返回时如何构建查询对象:
[undefined array element] Element 3 is undefined in a Java object of type class coldfusion.runtime.Array.
这似乎确实有效:
<cfset cfData = deserializeJson(returnData,'FALSE') />
<cfset qryData = cfData.data />
这让我可以像使用普通 cfquery 一样使用 qryData。
【问题讨论】:
-
尝试检查一个空字符串。
-
我不记得他们修复了哪个版本的 CF,但 CF 曾经将
NULL反序列化为"NULL"(即:作为值为 null 的字符串);它肯定在 CF9.0.1 中这样做。如果它在 CF10 中得到修复,您可能会在那里改变行为?另外:您没有在本地范围内限定您的数组计数器,如果您重用该对象,这可能会让您感到悲伤。如果其他函数使用i或k,或者如果您在多个线程中同时在同一个对象上运行此函数,则这可能相关。 -
它们在实际函数中是局部范围的——我只是删除了其中的一些,所以它不是一堵文字墙。我刚刚添加了一个包含 3 个值的简单字符串来显示错误。我看过你、Ben N. 和其他人的博客文章讨论了这个问题,但没有一个例子(到目前为止)适用于我遇到的问题。
-
在出错的行周围放置一个 try/catch,并转储所有参与的变量。这应该澄清发生了什么。
-
我现在所做的是将“FALSE”添加到 deserializeJSON strictMapping 标志中,这似乎会自动创建一个查询对象?我承认虽然这已经成为 CF10 的基础,但我可能错了。为了清晰起见,我将更新上面的代码。