Angular与C#中大数带小数自动舍入问题求助
解决Angular接收高精度decimal值时的舍入问题
问题的核心原因是:JavaScript的Number类型仅能精确表示2^53以内的数值,你数据库中的100000000000000.165已经超出这个范围,当API以数字类型返回该值时,浏览器会自动将其转换为Number类型,导致精度丢失——这就是你在网络面板看到舍入的原因,即使Angular中使用BigNumber接收,传输阶段的精度损失已经发生。
解决方案步骤:
1. 修改C# API的DTO,将decimal属性序列化为字符串传输
这样可以避免浏览器自动转换为Number类型,保留完整精度。根据你使用的JSON序列化库选择对应实现:
方案一:使用System.Text.Json(.NET Core 3.0+默认)
- 首先自定义一个decimal转字符串的转换器:
using System.Globalization; using System.Text.Json; using System.Text.Json.Serialization; public class DecimalAsStringConverter : JsonConverter<decimal?> { public override decimal? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { if (reader.TokenType == JsonTokenType.String && decimal.TryParse(reader.GetString(), out var value)) { return value; } return reader.TokenType == JsonTokenType.Null ? null : reader.GetDecimal(); } public override void Write(Utf8JsonWriter writer, decimal? value, JsonSerializerOptions options) { if (value.HasValue) { writer.WriteStringValue(value.Value.ToString(CultureInfo.InvariantCulture)); } else { writer.WriteNullValue(); } } } - 给DTO的属性添加转换器特性:
[JsonConverter(typeof(DecimalAsStringConverter))] public decimal? SctTotalPEO1 { get; set; }
方案二:使用Newtonsoft.Json(旧版本.NET常用)
- 自定义转换器:
using System.Globalization; using Newtonsoft.Json; public class StringDecimalConverter : JsonConverter { public override bool CanConvert(Type objectType) { return objectType == typeof(decimal) || objectType == typeof(decimal?); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { if (reader.Value is string str && decimal.TryParse(str, out var dec)) { return dec; } return reader.Value; } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { if (value is decimal dec) { writer.WriteValue(dec.ToString(CultureInfo.InvariantCulture)); } else if (value is decimal? nullableDec && nullableDec.HasValue) { writer.WriteValue(nullableDec.Value.ToString(CultureInfo.InvariantCulture)); } else { writer.WriteNull(); } } } - 给DTO属性添加特性:
[JsonProperty(ConverterType = typeof(StringDecimalConverter))] public decimal? SctTotalPEO1 { get; set; }
2. Angular端处理字符串转BigNumber
此时API返回的SctTotalPEO1是字符串类型,你需要将其转换为BigNumber使用:
// 先在实体中定义为string类型(或直接在响应处理时转换) export interface MyDto { sctTotalPEO1?: string; } // 接收响应后转换为BigNumber import BigNumber from 'bignumber.js'; // 假设从API获取数据 this.http.get<MyDto>('/api/xxx').subscribe(data => { const preciseValue = data.sctTotalPEO1 ? new BigNumber(data.sctTotalPEO1) : null; // 使用preciseValue进行后续操作 });
验证效果
修改后,在Angular的网络面板中查看响应,SctTotalPEO1会以字符串形式显示"100000000000000.165",转换为BigNumber后即可保留完整精度。
内容的提问来源于stack exchange,提问作者Asdf1234567
相关产品推荐
相关产品推荐

