防止 ColdFusion 使用 SerializeJSON 将字符串转换为数字
Posted
技术标签:
【中文标题】防止 ColdFusion 使用 SerializeJSON 将字符串转换为数字【英文标题】:Prevent ColdFusion from converting string to number using SerializeJSON 【发布时间】:2013-11-18 11:28:57 【问题描述】:我有带有最新修补程序 (4) 的 ColdFusion 9.0.1。 我需要 ColdFusion 返回所有带有引号的 JSON 数据(作为字符串)。我有以下问题:
<cfset test = StructNew()>
<cfset test.name = "1234.100">
<cfoutput>#SerializeJSON(test)#</cfoutput>
输出的文字是:
"name":1234.100
每个 javascript JSON 解析器都将其转换为 1234.1,并且不保留尾随的 0。我要么需要 ColdFusion 以字符串形式输出,要么需要 javascript 解析器来保留尾随的 0。有什么想法吗?
这是一个简化的例子。我正在从数据库中获取这些数据。
【问题讨论】:
将 0 替换为 xml 实体 不确定这是否可行,但 Ben Nadel 在 GitHub 上有一个项目,我听说它运行良好 github.com/bennadel/JsonSerializer.cfc 如果你在值前加上一个空格,CF 应该在将其转换为 json 时将其保留为字符串:<cfset test.name = " 1234.100">
。这仍然不理想,但可能会给你一些工作
【参考方案1】:
我知道这个问题很老了,但是作为一个新的 CF 开发人员,我遇到了同样的问题,虽然我成功使用了上面的“字符串 Hack”,但最后我从 Cold Fusion 文档中找到了更合适的解决方案 @ 987654321@。
'Adobe ColdFusion(2016 版)更新 2 使您能够为结构中的键指定数据类型信息。这称为元数据。'
<cfscript>
example = structnew();
example.firstname = "Yes";
example.lastname = "Man";
writeoutput("<b>After serialization</b>:");
// change the JSON key firstname to fname
metadata = firstname: type:"string",name:"fname";
example.setMetadata(metadata);
writeoutput(SerializeJSON(example));
</cfscript>
虽然该示例显示了修改字符串“Yes”的元数据以保持字符串,而不是转换为布尔值,但它同样适用于将数字转换为字符串以进行 JSON 序列化。
【讨论】:
是的,这就是答案。 这是否适用于旧版本的 CF?我在 CF2016 中进行了开发和分期,但 live 给了我与上述相同的问题及其 CF10(我认为)。难以调试和追踪。【参考方案2】:这是一个解决方案 - 尽管是一个非常老套、不优雅的解决方案......
您的设置:
var test =
name = "1234.100"
;
在前面添加一些明显的字符串会强制该值在转换为 JSON 时变为字符串。然后我们去掉这个丑陋的字符串。
var thisIsSuchAHorribleHack = "(!@$!@$)";
test.name = thisIsSuchAHorribleHack & test.name;
var serializedTest = SerializeJSON(test);
serializedTest = Replace(serializedTest, thisIsSuchAHorribleHack, "", "ALL");
writeOutput(serializedTest);
【讨论】:
【参考方案3】:如果您希望将一组变量视为字符串(例如邮政追踪号码“9449311899561067336896”),您可能会遇到 ColdFusion 认为字符串看起来像数字的问题。 ColdFusion 可能会尝试将字符串转换为整数,但如果它们对于整数来说太长,可能会导致错误。当字符串来自反序列化 JSON 中的数组时,可能会发生这种情况。
你可能认为你可以像这样使用字符串:
<cfset trackIdXml = "" />
<!--- Loop through all tracking numbers and build the XML --->
<cfloop array="#trackingNumsArray#" index="i">
<cfset trackIdXml &= "<TrackID ID=""" />
<cfset trackIdXml &= #trackingNumsArray[i]# />
<cfset trackIdXml &= """/>" />
</cfloop>
但是会导致Cannot convert the value 9.449311899561067E21 to an integer because it cannot fit inside an integer.
等错误
您可以改为使用 cfscript 和 java.lang.StringBuffer
:
<cfscript>
//This variable will store the XML that is used in the API request to list each tracking number
//We must tell ColdFusion that this is a string buffer, and use .append(). Why?
//ColdFusion will try to convert the tracking number to a integer if we do not explicitly tell it
//to treat it as a string.
trackIdXml = createObject("java", "java.lang.StringBuffer").init();
for (trackingNum in trackingNumsArray)
trackIdXml.append('<TrackID ID="');
trackIdXml.append(#trackingNum#);
trackIdXml.append('"/>');
</cfscript>
trackIdXml
变量是在 cfscript 标记内创建的,但仍可以像其他 Coldfusion 变量一样使用,例如在 cfreturn <cfreturn #trackIdXml# />
中使用
这是一个完整的真实示例,需要将类似整数的字符串保存为字符串。这是一个接受 USPS 追踪号码数组的函数,并从 USPS 的 API 返回包裹状态响应:
<cfcomponent>
<cffunction name="uspsLookup" access="remote" returntype="string" returnformat="plain" output="yes">
<cfargument name="trackingNums" type="string" required="yes" />
<cfset trackingNumsArray = DeserializeJSON(trackingNums, true) />
<cfscript>
trackIdXml = createObject("java", "java.lang.StringBuffer").init();
for (trackingNum in trackingNumsArray)
trackIdXml.append('<TrackID ID="');
trackIdXml.append(#trackingNum#);
trackIdXml.append('"/>');
</cfscript>
<cfset userid = "XXXXXXXXXXXX" />
<cfhttp
method="GET"
url='http://production.shippingapis.com/ShippingAPI.dll?API=TrackV2&XML=<TrackRequest USERID="#userid#">#trackIdXml#</TrackRequest>'>
</cfhttp>
<cfif #cfhttp.Statuscode# IS "200 OK" >
<cfreturn "#cfhttp.Filecontent#">
<cfelse>
<cfreturn "error||#cfhttp.Statuscode#">
</cfif>
</cffunction>
</cfcomponent>
【讨论】:
【参考方案4】:只需在号码的开头添加一个简单的空格即可。 最后我尝试了,但它不起作用。
<cfset test = StructNew()>
<cfset test.name = " 1234.100">
<cfoutput>#SerializeJSON(test)#</cfoutput>
输出将是
"name":" 1234.100"
【讨论】:
这确实有效,但它是一个kludge。我决定使用第三方 json 编码器/解码器。【参考方案5】:如果您不想使用 kludge,可以使用正确编码 JSON 的第三方库。我使用来自http://jsonutil.riaforge.org/ 的 JSONUtil。我使用的是 ColdFusion 9,所以不知道最新版本的 ColdFusion 是否修复了一些编码异常。
【讨论】:
以上是关于防止 ColdFusion 使用 SerializeJSON 将字符串转换为数字的主要内容,如果未能解决你的问题,请参考以下文章
禁止保存()以防止由于未保存的相关对象“postid”而导致数据丢失
Coldfusion 2016 - “此版本的ColdFusion服务器不支持高级调度支持。”