項目中使用 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));
啰嗦了這么,希望通過升級版本解決同樣遇到這樣問題的小伙伴。