Json.NET 反序化小數數值解析問題
2 |
我有段將彈性格式 JSON 反序列化為 Dictionary<string, object> 的程式,在處理小點數時遇上問題。假設 JSON 來源長這樣:
[
{
"ItemNo": "A-100",
"Value": 127
},
{
"ItemNo": "A-101",
"Value": 3.1416
},
{
"ModelId": "B-52",
"Value": 0.00000000035
},
{
"ModelId": "B-1",
"Value": 9.87987987987987987
}
]
解析程式如下:
static void Main(string[] args)
{
var srcJson = File.ReadAllText("sample.json");
Console.WriteLine(srcJson);
var data = JsonConvert.DeserializeObject<Dictionary<string, object>[]>(srcJson);
Console.WriteLine(JsonConvert.SerializeObject(data, Formatting.Indented));
Console.ReadLine();
}
原本預期 Value 欄位會解析成 decimal 型別,事實不然。反序列化後數值有變,再序列化後 0.00000000035 變成 3.5E-10, 9.87987987987987987 變成 9.87987987987988,損失部分精確度。
由科學記號及位數取 15 位,判斷它們是被當成 double,透過檢查 dict["Value"].GetType() 可驗證這點。
幸好,Json.NET 有個序列化參數 FloatParseHandling,設成 FloatParseHandling.Decimal 可強制將浮點數字解析成 Decimal,問題排除。
Issue of precison loss while JSON deserialization and how to avoid it in Json.NET.
Comments
# by Cloud
黑大, 使用 System.Text.Json 可正確處理小數數值解析問題 var data = JsonSerializer.Deserialize<Dictionary<string, object>[]>(srcJson); Console.WriteLine(JsonSerializer.Serialize(data, new JsonSerializerOptions() { WriteIndented = true }));
# by Jeffrey
to Cloud, 正好奇 System.Text.Json 會不會遇到同樣問題,謝謝分享。