System.Text.Json序列化器为何会移除小数末尾的零?
System.Text.Json序列化器为何会移除小数末尾的零?
嘿,这个问题我之前做财务系统的时候可踩过不小的坑!其实这是System.Text.Json的默认序列化行为导致的——它处理decimal类型时,会自动剔除末尾的零,核心原因是它默认按照「最小有效数字」来序列化数值,目的是精简JSON的体积,毕竟从纯数值角度来说,12.500和12.5完全等价,多余的零确实是没必要的冗余内容。
但如果你的场景(比如金额、精确计量数据)必须保留末尾的零,那可以试试这几个解决办法:
自定义JsonConverter(最灵活)
自己写一个转换器完全掌控序列化逻辑,比如要强制保留2位小数(常见的金额场景),代码大概是这样的:public class FixedDecimalConverter : JsonConverter<decimal> { private readonly int _decimalPlaces; public FixedDecimalConverter(int decimalPlaces = 2) { _decimalPlaces = decimalPlaces; } public override decimal Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { return reader.GetDecimal(); } public override void Write(Utf8JsonWriter writer, decimal value, JsonSerializerOptions options) { // 按指定格式输出,强制保留指定位数的小数 var formattedValue = value.ToString($"F{_decimalPlaces}"); writer.WriteStringValue(formattedValue); } }用的时候只需要把转换器加到序列化选项里就行:
var serializeOptions = new JsonSerializerOptions(); serializeOptions.Converters.Add(new FixedDecimalConverter(2)); var jsonString = JsonSerializer.Serialize(yourDataObject, serializeOptions);针对单个属性配置(局部生效)
如果你只需要给某个特定的decimal属性保留末尾零,不用全局加转换器,直接在属性上标记[JsonConverter]特性就行:public class Order { public int Id { get; set; } [JsonConverter(typeof(FixedDecimalConverter))] public decimal Amount { get; set; } }精准保留原始小数位数
要是你想保留decimal本身携带的小数位数(比如有的值是1.0,有的是2.500),可以利用decimal的内部位信息来实现:public override void Write(Utf8JsonWriter writer, decimal value, JsonSerializerOptions options) { // 从decimal的内部位数据中提取原始小数位数 var bits = decimal.GetBits(value); var originalScale = (bits[3] >> 16) & 0x7F; var formattedValue = value.ToString($"F{originalScale}"); writer.WriteStringValue(formattedValue); }
备注:内容来源于stack exchange,提问作者Post Impatica
相关产品推荐
相关产品推荐

