使用System.Text.Json序列化.NET对象时double属性值精度异常求助
解决System.Text.Json序列化double时的精度显示问题
问题原因
你遇到的现象确实和double的二进制浮点特性直接相关:
- 像70.8这样的十进制小数无法被二进制浮点数精确存储,在内存中它实际的二进制表示对应的十进制近似值就是
70.799999999999997。 - 类实例中显示70.8,是因为.NET在调试器、
ToString()等场景下会自动对这个近似值做舍入处理,以更友好的十进制形式展示;但System.Text.Json默认会输出double的精确二进制浮点对应十进制字符串,所以就出现了看似“数值变化”的情况。
解决方案
以下两种方法可以在不将double转为字符串的前提下,让JSON输出更友好的数字格式:
方法1:自定义转换器,按指定精度舍入输出
创建一个JsonConverter<double>的实现,序列化时主动将double值舍入到指定小数位:
public class DoubleRoundingConverter : JsonConverter<double> { private readonly int _decimalPlaces; public DoubleRoundingConverter(int decimalPlaces = 1) { _decimalPlaces = decimalPlaces; } public override double Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { return reader.GetDouble(); } public override void Write(Utf8JsonWriter writer, double value, JsonSerializerOptions options) { var roundedValue = Math.Round(value, _decimalPlaces); writer.WriteNumberValue(roundedValue); } }
修改Well类的序列化方法,配置使用该转换器:
public void serialiseJSON() { string fileName = "well.json"; var options = new JsonSerializerOptions { Converters = { new DoubleRoundingConverter(1) }, // 根据需求调整小数位数 WriteIndented = true // 可选,格式化JSON结构 }; // 注意:原代码中JsonSerialiser拼写错误,应为JsonSerializer string jsonString = JsonSerializer.Serialize(this, options); File.WriteAllText(fileName, jsonString); }
这种方法适合你明确知道业务所需精度的场景,比如长度值只需保留1位小数。
方法2:输出double的最短精确表示
利用double.ToString("G17")格式,输出能唯一标识该double值的最短十进制字符串,既保证精度又避免冗长数字:
public class DoubleShortFormatConverter : JsonConverter<double> { public override double Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { return reader.GetDouble(); } public override void Write(Utf8JsonWriter writer, double value, JsonSerializerOptions options) { // G17格式会输出最短的、能精确还原原double值的十进制字符串 writer.WriteRawValue(value.ToString("G17")); } }
同样在序列化配置中添加该转换器即可,这种方法适合需要保留double原始精度,但不想看到冗长近似值的场景。
注意事项
- 两种方法反序列化后得到的
double值,和原实例中的值在二进制层面是等价的(因为原double本身就是近似值),不会丢失业务精度。 - 原代码中的
JsonSerialiser是拼写错误,正确的类名是JsonSerializer。
内容的提问来源于stack exchange,提问作者Suhaib Ahmad
相关产品推荐
相关产品推荐

