fastjson 處理 double 的精度問題


項目中使用 fastjson 來處理 json 格式,當前使用的版本為1.1.37。在和其它系統交互時,將一個json串傳給了對方,原值為5.0,json 處理后格式為:{"dou", 5}; 結果對方處理該串報錯了, 原因是他將串整理轉成 Map ,在取值時強制轉為了 Double ,因為拿到的值轉化是 Integer 類型,強轉肯定異常了。 簡單的做法應該通過 Double.valueOf(value)  進行處理。但無奈合作方不願意處理。 於是測試了下fastjson處理這個串時,通過以下做處理, 輸出的結果為 {"dou", 5}。

JSONObject jsonObject = new JSONObject();
Double dou = new Double(5.0);
jsonObject.put("dou", dou);
System.out.println(JSON.toJSONString(jsonObject));

想要輸出{"dou",5.0} 怎么辦, 跟蹤了下源碼,發現在 DoubleSerializer 的 write 方法中,判斷了結尾如果是.0 就截掉了。

doubleText = Double.toString(doubleValue);
if(doubleText.endsWith(".0")) {
    doubleText = doubleText.substring(0, doubleText.length() - 2);
}

那想要的格式怎么辦,可以通過自定義 filter 方式實現,:

 ValueFilter filter = new ValueFilter() {
            @Override
            public Object process(Object object, String name, Object value) {
                if(value instanceof BigDecimal || value instanceof Double || value instanceof Float){
                    return new BigDecimal(value.toString());
                }
                return value;
            }
        };

String s  = JSON.toJSONString(jsonObject, filter, new SerializerFeature[0]);

以上可以完美解決。后來想有沒有跟好的方法呢。 於是網上搜索了一下,大多數都是這種做法,並且有人認為這是一個bug,於是突然想有沒有可能 wenshao 會處理一下,於是在 github 找到 fastjson 的最新版本 1.2.23。 先修改 pom 文件,然后運行。發現即使不處理也能輸出了 {"dou",5.0} 。 於是 debug 進去原來對 DoubleSerializer 進行了重寫,並在 write 方法中原來處理格式的地方修改為如下:

if (decimalFormat == null) {
    out.writeDouble(doubleValue, true);
} else {
    String doubleText = decimalFormat.format(doubleValue);
    out.write(doubleText);
}

//out SerializeWriter
String doubleText = Double.toString(doubleValue);
if (isEnabled(SerializerFeature.WriteNullNumberAsZero) && doubleText.endsWith(".0")) {
    doubleText = doubleText.substring(0, doubleText.length() - 2);
}

即,以上粉色代碼調用 SerializeWriter 的writeDouble 方法, 看綠色部分。 同時判斷了 SerializerFeature.WriteNullNumberAsZero 和 結尾是否為 .0

就是通過這個解決了 double 精度的正常輸出。  在使用 1.2.23時如果想輸出{"dou", 5}, 可以通過設置 SerializerFeature.WriteNullNumberAsZero 實現。

System.out.println(JSON.toJSONString(jsonObject, SerializerFeature.WriteNullNumberAsZero));

啰嗦了這么,希望通過升級版本解決同樣遇到這樣問題的小伙伴。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM