我试图通过一个函数传递一个struct,但是它中的整数正在转换为科学记数法。
在去科学化之前:
{"businessUnitValidList":2003051509034372557922
, "shortMessage":"Success"
, "longMessage":"Request Completed Successfully."
, "status":20001
}
去科学化后:
businessUnitValidList 2.00305150903E+021
我已经尝试将其转换为字符串,但它仍然给我相同的输出。有什么想法吗?
注意:如果我的businessUnitValidList
中有多个值,则数字会以他们应该的方式显示。
修改
这是当前的代码迭代:
<cfloop array="#businessUnitArray#" index="i">
<cfquery name="validatebusinessUnit" datasource="dbproduction">
select doctorid from survey.dbo.clientLocationMap
where clientbrandid = '#arguments.clientBrandid#'
and clientLocation = '#i#'
</cfquery>
<cfif validatebusinessUnit.recordcount gt 0>
<cfset businessUnitValidList = listAppend(businessUnitValidList,toString(validatebusinessUnit.doctorid),",")>
<cfelse>
<cfset businessUnitInValidList = listAppend(businessUnitInValidList,i,",")>
</cfif>
</cfloop>
<cfif businessUnitInValidList neq ''>
<cfset ResponseStruct['BusinessUnitCodes']['businessUnitMixResponse']['businessUnitInValidList'] = "#businessUnitInValidList#">
<cfset ResponseStruct['BusinessUnitCodes']['businessUnitMixResponse']['businessUnitValidList'] = "#businessUnitValidList#">
<cfreturn serializeJSON(ResponseStruct['BusinessUnitCodes']['businessUnitMixResponse'])>
<cfelse>
<cfset ResponseStruct['BusinessUnitCodes']['businessUnitSuccess']['businessUnitValidList'] = "#businessUnitValidList#">
<cfreturn serializeJSON(ResponseStruct['BusinessUnitCodes']['businessUnitSuccess'])>
</cfif>
答案 0 :(得分:7)
ColdFusion的JSON序列化存在问题,可能因版本甚至修补程序而异。正如Jedihomer Townend在评论中提到的那样,领先的空间应该强迫CF将其视为一个字符串,而不是强制它。
我刚刚在CF10,11和2016上试过这个并保留了输入。
<cfscript>
a = {
"businessUnitValidList":" 2003051509034372557922",
"shortMessage":"Success",
"longMessage":"Request Completed Successfully.",
"status":20001
};
json = serializeJSON(a);
b = deserializeJSON(json);
writeDump(b);
</cfscript>
你可以在这里试试:
http://trycf.com/gist/70b86fbb57f752125f35/acf?theme=monokai
答案 1 :(得分:4)
在java中,我们使用BigInteger数据类型来存储大值。在Coldfusion中,我们可以使用JavaCast转换为整数,长整数和双精度。但问题在于,即使是“长期”也是如此。数据类型只能存储19位数。
通过将数字转换为字符串,执行数学运算可能会有问题。在这里,我们可以在执行数学运算时使用precisionEvaluate()。
PrecisionEvaluate函数可以让你计算任意长的十进制数 (BigDecimal precision)值。 BigDecimal精度算术接受 并生成任意长度的十进制数。
在此示例中,您可以像这样使用:
<cfset ResponseStruct['BusinessUnitCodes']['businessUnitMixResponse']['businessUnitInValidList'] = "#precisionEvaluate(businessUnitInValidList)#">
答案 2 :(得分:4)
(评论太长)
我的代码正在生成正确的结果是deserializeJSON() 引起了这个问题。
不完全。 JSON 值是正确的,但序列化省略了周围的引号。这意味着在反序列化期间,该值将作为数字类型处理,从而导致您观察到的问题。除非您可以强制序列化将值视为字符串,否则反序列化的结果将始终是错误的。作为Carl Von Stetten already mentioned,这是一个错误。 Jedihomer Townend对appending a space character的回答可能是最简单的解决方法。
更长的回答:
尽管CF11的JSON处理得到了改进,但CF仍然有点过于“有用”......正如您所指出的,CF在序列化时检测到值为数字并省略了周围的引号。因此将值类型标记为数字。
{..."businessUnitValidList":2003051509034372557922 }
听起来很棒,直到你尝试反序列化。如果值用引号括起来,它将作为字符串处理,并保留原始值。不幸的是,没有引号它被认为是数字,这意味着CF必须将值填入one of its two numeric data types:
java.lang.Double
或java.lang.Integer
maximum value of an Integer是2147483647.显然你的数字太大了,所以CF将它转换为java.lang.Double。出于两个原因,这是一个问题。首先,Double是approximate type。其次,根据该类的规则,scientific notation may be used when representing the number as a String,即当变量与cfoutput或cfdump一起显示时。这就是为什么反序列化的结果看起来与你期望的不同。除非您可以强制它在序列化时被视为字符串,否则反序列化的结果将始终是错误的。
公平地说,CF11确实包含了对JSON处理的一些改进。不幸的是,大多数都围绕着cfc和查询对象。鉴于您当前的结构,它不会完全工作。但是,如果您能够使用单个查询对象,则可以借助新的应用程序级别设置this.serialization.serializeQueryAs = "struct";
来解决问题。与早期版本相比,它为序列化查询强制采用更合理的格式。由于CF11在序列化时遵循列数据类型,因此如果列数据类型为BIGDECIMAL,则会保留该值,或者将其转换为VARCHAR。不幸的是,CF仍然是大写查询列名称,但保留了基本值。
<强>结果:强>
[ { "BUSINESSUNITVALIDLIST" : "2003051509034372557922",
"LONGMESSAGE" : "Request Completed Successfully.",
"SHORTMESSAGE" : "Success",
"STATUS" : 20001
} ]
<强>代码:强>
qry = queryNew("");
queryAddColumn(qry, "businessUnitValidList", "varchar", ["2003051509034372557922"]);
queryAddColumn(qry, "shortMessage", "varchar", ["Success"]);
queryAddColumn(qry, "longMessage", "varchar", ["Request Completed Successfully."]);
queryAddColumn(qry, "status", "integer", [20001]);
json = serializeJSON(qry);
writeDump(deserializeJSON(json));
CF11还引入了自定义序列化器/反序列化器,可能在这里工作。虽然这个特定任务可能有点过头了。
说了这么多,最简单的选择就是使用“附加非数字字符”黑客。好吧..或者切换到自定义库,可以使用JSON处理执行更一致的工作; - )
旁注/效率:
除非有一个特定的原因,你必须在循环中执行查询,否则可能有更高效的选项(特定于dbms,你没有提到)。另外,不要忘记在所有变量查询参数上使用cfqueryparam
。其中许多好处是在多次执行相同查询时提升性能 - 例如在循环内。