JSON反序列化后double/decimal显示为科学计数法是ToString()默认行为,数值精度未丢失;金额等高精度场景应使用decimal而非double,并确保JSON中数字不带引号。

JSON反序列化后double或decimal变成1.2345E+10这类科学计数法显示
这不是反序列化出错了,而是ToString()默认行为——double和float在转字符串时,.NET会自动用科学计数法表示“过大”或“过小”的值。实际数值没丢精度,只是显示吓人。
常见场景:API返回{"price":123456789.12},反序列化成double price后打印price.ToString(),输出1.2345678912E+08。
- 别在日志或UI里直接
.ToString()原始double,改用.ToString("G")(通用格式)或"F2"等显式格式 - 如果业务要求高精度(比如金额),反序列化目标类型别用
double,改用decimal——它不走IEEE 754浮点规则,不会触发科学计数法默认逻辑 -
JsonSerializer.Deserialize<T>(System.Text.Json)对decimal字段默认就能精确还原,只要JSON里是合法数字字面量(不含引号)
用System.Text.Json反序列化decimal却得到0或抛JsonException
典型原因是JSON里数字被包了双引号,比如{"amount":"123.45"}。此时System.Text.Json默认不把字符串自动转decimal,直接失败或静默归零(取决于配置)。
DMap GL地图JSAPI(dmapgl)开发指南。用于编写、审查、调试 DMap 地图 API 代码,涵盖地图初始化、覆盖物渲染、图层管理、事件处理、控件交互等任务。当用户提及 dmap、dmapgl、jsapi‑gl 或相关地图开发需求时自动触发。
- 检查原始JSON:用
JsonDocument.Parse()先粗略看下amount节点的ValueKind是Number还是String - 若服务端无法改JSON格式,可注册自定义
JsonConverter<decimal>,在Read方法里判断refTokenType == JsonTokenType.String再decimal.TryParse - 避免全局开
PropertyNameCaseInsensitive = true以外的宽松模式——它不解决字符串数字问题,反而掩盖类型不匹配
Newtonsoft.Json里float/double反序列化后计算结果异常
根本原因不是JSON库,而是float和double本身的二进制浮点限制。例如0.1 + 0.2 != 0.3,反序列化只是把那个“本来就不精确”的二进制值读进来而已。
- 涉及货币、计数、ID等必须精确的场景,强制约定服务端传数字不带引号,并在C#端用
decimal接收 - Newtonsoft.Json默认把JSON数字映射到
double,哪怕你声明字段是decimal——必须配JsonSerializerSettings.FloatParseHandling = FloatParseHandling.Decimal - 别依赖
Convert.ToDecimal(obj)去救场:如果obj已经是double类型,再转decimal只会把误差固化下来
想保留JSON里原始数字字符串(比如超长整数ID不被截断)
64位整数在JavaScript里超过Number.MAX_SAFE_INTEGER(9007199254740991)就会丢失精度。C#用long接可能溢出,用double接则必然不准。
- 最稳方案:把ID字段声明为
string,跳过数字解析,后续需要时再按需转BigInteger或校验格式 - System.Text.Json从.NET 6起支持
JsonSerializerOptions.NumberHandling = JsonNumberHandling.AllowReadingFromString,配合long?字段可容忍带引号的数字字符串 - Newtonsoft.Json需手动加
[JsonConverter(typeof(StringToNumberConverter))],但注意这不能挽回JS端已丢失的精度
关键点容易被忽略:科学计数法只是显示问题,而精度丢失是数据源头就发生的——得先分清你遇到的是“看起来怪”还是“算出来错”。

















