Long Integers正在转换为科学记数法 - ColdFusion

时间:2016-03-17 11:14:19

标签: struct coldfusion

我试图通过一个函数传递一个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>

3 个答案:

答案 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

  1. 实数或浮点数,即java.lang.Double
  2. 32位整数,即java.lang.Integer
  3. 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。其中许多好处是在多次执行相同查询时提升性能 - 例如在循环内。