如何确保SerializeJSON保持尾随/前导零?

时间:2013-05-21 20:40:56

标签: json serialization coldfusion coldfusion-9

编辑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 number(14,2)

当我使用Coldfusion 9.0.1(cfscript,如果它重要)查询时,这里是一个RC转储,注意id字符串保留前导零,但数字列已删除尾随零。 enter image description here 虽然这很有趣,但它对原始问题无关紧要,因为我可以手动创建一个查询以保留如下所示的尾随零,它仍然会在serializeJSON中丢失 enter image description here

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

<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,但由于注释文本区域包含撇号等,这将返回无效的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""
    },

2 个答案:

答案 0 :(得分:3)

这有点令人费解......我也在CF 9中测试过。不知道你在处理序列化数据(作为服务传递,在页面上输出等),我把一些测试模式放在一起。一种可能的解决方案是,如果只是尝试序列化唱歌值 - 不要。实际上,您可以在不进行序列化的情况下对数值运行反序列化,并且它所做的只是去除尾部0.否则,如果必须序列化单个值并且不希望删除尾部0,请将变量设置为包含引号< / p>

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

答案 1 :(得分:2)

取自评论

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

Raymond Camden撰写的这篇博客文章讨论了9.0.1中所做的更改 - Not happy with the CF901 JSON Changes?

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

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

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