3

编辑 3 Coldfusion 9.0 存在以下问题,更新到 9.0.1 确实解决了这个问题

我有一个使用 SerializeJSON 对查询结果进行编码的应用程序:

#SerializeJSON('Ok works fine')#

不幸的是,它会从数字中修剪尾随零:

#SerializeJSON(12345.50)#

如果我要手动将相同的值设为字符串,则会发生同样的事情

#SerializeJSON('12345.50')#

我怎样才能防止这种情况发生?

编辑- 我的场景细节

数据库 (Oracle) 将这些示例值存储在一行中

  • benefactor_id : 0000729789 varchar2(10)
  • life_gift_credit_amt:12345.50 号码(14,2)

当我使用 Coldfusion 9.0.1 (cfscript if it matter) 查询时,这是一个 RC 转储,请注意 id 字符串保留前导零,但数字列已删除尾随零。 在此处输入图像描述 虽然这很有趣,但这与原始问题无关,因为我可以手动创建一个查询来保留下面的尾随零,它仍然会在 serializeJSON 中丢失 在此处输入图像描述

我获取查询结果,并使用 serializeJSON 对值进行编码。JSON 由 jquery Datatables ajax 使用。请注意,id 字符串已变为数字,并添加了 Miguel-F 提到的“.0”

<cfscript>
...
  rc.sql = q.setsql;
  rc.qResult = q.execute().getresult();

  savecontent variable="rc.aaData" {
    for (i=1; i <= rc.qResult.RecordCount; i++) {
      writeOutput('{');
      for (col=1; col <= iColumnsLen; col++) {
        // the following line contains a conditional specific to this example
        writeOutput('"#aColumns[col]#":#SerializeJSON(rc.qResult[aColumns[col]][i])#'); 
        //former statement, discarded due to not being able to handle apostrophe's ... writeOutput('"#jsStringFormat(rc.qResult[aColumns[col]][i])#"');
        writeOutput((col NEQ iColumnsLen) ? ',' : '');
      }
      writeOutput('}');
      writeOutput((i NEQ rc.qResult.RecordCount) ? ',' : '');
    }
  };
</cfscript>  

我最初使用的是 jsStringFormat 而不是 serializeJSON,但是由于评论文本区域包含撇号的 ect,这将返回无效的 JSON

{
    "sEcho": 1,
    "iTotalRecords": 65970,
    "iTotalDisplayRecords": 7657,
    "aaData": [
        {
            "nd_event_id": 525,
            "benefactor_id": 729789.0,
            "seq_number": 182163,
            "life_gift_credit_amt": 12345.5,
            "qty_requested": 2,
            "b_a_comment": "#swap",
            "pref_mail_name": "Jay P. Rizzi"
        }
    ]
}

编辑 2

一个快速的旁注,如果我将我的序列化行更改为

writeOutput('"#aColumns[col]#": "#SerializeJSON(rc.qResult[aColumns[col]][i])#"'); 

然后我的结果集更改为将记录放在双引号中,但也将双引号字符串放在双引号中,同时仍删除尾随零;它让我相信 serializeJSON 将值转换为类型?

"aaData": [
    {
        "nd_event_id": "525",
        "benefactor_id": "729789.0",
        "seq_number": "182163",
        "life_gift_credit_amt": "12345.5",
        "qty_requested": "2",
        "b_a_comment": ""#swap"",
        "pref_mail_name": ""JayP.Rizzi""
    },
4

2 回答 2

3

这有点莫名其妙......我也在 CF 9 中进行了测试。我不知道你在用序列化数据做什么(作为服务传递、在页面上输出等),我整理了一些测试模式。一种可能的解决方案是,如果只是尝试序列化一个单值 - 不要。您实际上可以在不序列化的情况下对您的数值运行反序列化,它所做的只是去除尾随的 0。否则,如果您必须序列化单个值并且不希望去除尾随的 0,请将变量设置为包含引号

<cfset manualserial = '"111.10"'>
<cfdump var="#DeSerializeJson(manualserial)#">

此时您可以使用反序列化并查看它是否保持 0,输出为 111.10 下面是一些额外的测试,因此您可以看到在尝试保持尾随 0 的同时序列化数组时会发生什么……不走运。但是,当我放弃内置的 CF 序列化并刚刚创建了一个序列化字符串时,将保留尾随 0(请参阅下面 WriteDump 示例中的 var customarr 和 d_customarr )。

希望能有所帮助。

<cfscript>
/*initial testing*/
string = SerializeJSON('Ok works fine');
numericstring = SerializeJSON('12345.50');
numeric = SerializeJSON(12345.50);
arr =  SerializeJSON([12345.50,12345.10,'12345.20']);
arrFormat = SerializeJSON([NumberFormat(12345.50,'.00') & ' ',12345.10,'12345.20']);

d_string = DeSerializeJSON(string);
d_numericstring = DeSerializeJSON(numericstring);
d_numeric = DeSerializeJSON(numeric);
d_arr = DeSerializeJSON(arr);
d_arrFormat = DeSerializeJSON(arrFormat);


/*technically, there is no need to serialize a single string value, as running through DeSerialize just trims the trailing 0
if you need to do so, you would want to pass in as a string with quotation marks*/
customstring = '"12345.50"';
d_customstring  = DeSerializeJSON(customstring);
customarr = '["12345.50","12345.10","12345.20"]';   //--you can format your own array instead of using CF to serialize 
d_customarr  = DeSerializeJSON(customarr);

WriteDump(variables);
</cfscript>

=======附加可能的解决方案 b========

我认为手动序列化你的记录可能是最稳定的选择,试试这个例子,如果它有效,你应该能够将该函数添加到 cfc 或创建一个 udf 以供重用。希望能帮助到你。

<cfscript>
q = QueryNew('nd_event_id,benefactor_id,seq_number,life_gift_credit_amt,qty_requested,b_a_comment,pref_mail_name',
            'Integer,VarChar,Integer,Decimal,Integer,VarChar,VarChar');
r = queryaddrow(q,2);   
querysetcell(q, 'nd_event_id', 525, 1);
querysetcell(q, 'benefactor_id', 0000729789, 1);    
querysetcell(q, 'seq_number', 182163, 1);
querysetcell(q, 'life_gift_credit_amt', 12345.50, 1);   
querysetcell(q, 'qty_requested', 2, 1); 
querysetcell(q, 'b_a_comment', '##swap', 1);    
querysetcell(q, 'pref_mail_name', 'Jay P. Rizzi', 1);       
querysetcell(q, 'nd_event_id', 525, 2);
querysetcell(q, 'benefactor_id', 0000729790, 2);
querysetcell(q, 'seq_number', 182164, 2);   
querysetcell(q, 'life_gift_credit_amt', 12345.90, 2);   
querysetcell(q, 'qty_requested', 10, 2);    
querysetcell(q, 'b_a_comment', '##swap', 2);    
querysetcell(q, 'pref_mail_name', 'Jay P. Rizzi', 2);   
WriteDump(q);

s = membershipManualSerializer(q);

public string function membershipManualSerializer(required query q){
    var jsonString = '{"aaData":[';
    var cols = listtoarray(q.columnList,',');

    for(var i=1; i lte q.recordcount; i++){

        jsonString &= "{";

        for(var c=1;c lte arraylen(cols);c++){
            jsonString &= '"' & cols[c] & '":"' & q[cols[c]][i] & '"';
            jsonString &= (c lt arraylen(cols))? ",":"";
        }

        jsonString &= (i lt q.recordcount)? "},":"}]";
    }

    jsonString &="}";

    return jsonString;
}


WriteOutput(s);
WriteDump(DeserializeJson(s));      
</cfscript>
于 2013-05-22T13:01:55.240 回答
2

取自评论

这个问题的原始海报(OP)最初报告说他们在 ColdFusion 9.0.1 中遇到了这个问题。事实证明,他们实际上运行的是 ColdFusion 9.0.0。SerializeJSON()这很重要,因为 Adob ​​e 在 9.0.1 版本中对该函数处理数字的方式进行了更改。当服务器升级到版本 9.0.1 时,这些问题得到了解决。

Raymond Camden 的这篇博客文章讨论了 9.0.1 中所做的更改 -对 CF901 JSON 更改不满意?

在该博客文章中,他引用了已输入的错误 83638,然后在版本 9.0.1 的 HotFix 1 中修复 - ColdFusion 9.0.1 的累积修补程序 1 (CHF1)

如果您在版本 9.0.1 下搜索 JSON 的BugBase,则有几个报告与 OP 相同的问题。

这些报告的错误还提到了 OP 最初没有报告的另一个问题,即 a.0也被附加到整数。后来在讨论中,OP 证实他们也看到了这种行为。这导致他们验证正在使用的 ColdFusion 版本,发现它不是 9.0.1。

于 2013-05-23T19:09:57.657 回答