Dot-Net
Json.NET 用最少的小數位序列化浮點/雙精度,即沒有多餘的“.0”?
在序列化浮點數和雙精度數時,如果數字不包含任何小數部分,Json.NET 總是在末尾添加“.0”。我想知道是否有一種簡單的方法可以繞過它,從而產生更緊湊的表示?序列化包含許多數字的對象時,額外的句點和零會加起來。
例如,執行此程式碼時:
JsonConvert.SerializeObject(1.0);我希望(並且想要)這個結果:
"1"但相反,我得到:
"1.0"我查看了原始碼並註意到它是故意添加到送出0319263(“…-Fixed JsonConvert to always write a floating point number with a decimal place…”)中,它執行的程式碼基本上看起來像:
private static string EnsureDecimalPlace(double value, string text) { if (double.IsNaN(value) || double.IsInfinity(value) || text.IndexOf('.') != -1 || text.IndexOf('E') != -1 || text.IndexOf('e') != -1) { return text; } return text + ".0"; }因此,我想知道:
- 這種變化的原因可能是什麼?JSON 規範似乎不需要它。
- 有沒有簡單的方法繞過它?
1. 發生這種變化的原因可能是什麼?
規範不需要它,但它也不允許它。
我的猜測是它允許對 Json.NET 進行更好的類型檢查(如果他們在某處有它),或者它是一個“以防萬一”的東西,允許區分整數和浮點類型。
2.有沒有簡單的方法繞過它?
EnsureDecimalPlace()沒那麼容易,但是如果你真的想要的話,你可以在改成 simple 之後重新編譯你自己的 Json.NET 版本return text;
作為問題 2 的替代答案(假設您不想經歷編譯自己的 Json.NET 源的自定義版本的麻煩),您可以創建自己的自定義 JsonConverter 類來處理小數、浮點和雙精度值。這是我正在使用的版本:
class DecimalJsonConverter : JsonConverter { public DecimalJsonConverter() { } public override bool CanRead { get { return false; } } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { throw new NotImplementedException("Unnecessary because CanRead is false. The type will skip the converter."); } public override bool CanConvert(Type objectType) { return (objectType == typeof(decimal) || objectType == typeof(float) || objectType == typeof(double)); } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { if (DecimalJsonConverter.IsWholeValue(value)) { writer.WriteRawValue(JsonConvert.ToString(Convert.ToInt64(value))); } else { writer.WriteRawValue(JsonConvert.ToString(value)); } } private static bool IsWholeValue(object value) { if (value is decimal) { decimal decimalValue = (decimal)value; int precision = (Decimal.GetBits(decimalValue)[3] >> 16) & 0x000000FF; return precision == 0; } else if (value is float || value is double) { double doubleValue = (double)value; return doubleValue == Math.Truncate(doubleValue); } return false; } }這將保留十進制類型值的精度。如果您希望忽略小數值的精度,可以使 IsWholeValue() 函式的小數部分與浮點/雙精度部分的工作方式相同:
private static bool IsWholeValue(object value) { if (value is decimal) { decimal decimalValue = (decimal)value; return decimalValue == Math.Truncate(decimalValue); } else if (value is float || value is double) { double doubleValue = (double)value; return doubleValue == Math.Truncate(doubleValue); } return false; }無論哪種情況,要使用上面的程式碼,只需像這樣呼叫序列化程序:
string json = JsonConvert.SerializeObject(value, new DecimalJsonConverter())
