You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET Framework 4.7 WebAPI返回long类型值到Angular前端出现精度偏差

问题根因

你遇到的数值偏差确实是自动四舍五入(rounding)导致的,核心原因如下:

  • JavaScript 内置的Number类型为双精度64位浮点数,仅支持范围在[-9007199254740991, 9007199254740991](即 ±2^53-1)的安全整数,超出该范围的整数值无法被精确存储
  • 本次出现偏差的数值9997773333333335远大于2^53的上限,浏览器默认调用JSON.parse()解析接口返回的JSON时,会自动将超出精度的长整数四舍五入,最终就出现了+1的偏差
  • 后端.NET的long类型、数据库Bigint类型本身支持64位整数的完整精度,因此后端调试、数据库存储的数值都是正常的,问题仅出在前后端数据传输后的JSON解析环节
解决方案

方案1:后端改造(优先推荐,兼容性最好)

直接将.NET接口返回对象中的long类型字段序列化为字符串输出,从根源避免前端精度丢失,操作方式可选择全局配置或单独字段配置:

全局配置(所有long类型自动转字符串)

在WebApiConfig的Register方法中添加序列化配置:

using Newtonsoft.Json;
using Newtonsoft.Json.Converters;

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        // 其他原有配置...
        
        // 配置long类型序列化为字符串
        config.Formatters.JsonFormatter.SerializerSettings.Converters.Add(
            new CustomLongToStringConverter()
        );
    }
}

// 自定义Long转String序列化转换器
public class CustomLongToStringConverter : JsonConverter<long>
{
    public override void WriteJson(JsonWriter writer, long value, JsonSerializer serializer)
    {
        writer.WriteValue(value.ToString());
    }

    public override long ReadJson(JsonReader reader, Type objectType, long existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        return long.Parse(reader.Value?.ToString() ?? "0");
    }
}

单独字段配置(仅指定long字段转字符串)

给DTO类中对应的long类型字段添加序列化特性即可:

public class YourResponseDto
{
    [JsonConverter(typeof(StringConverter))]
    public long YourBigintField { get; set; }
    // 其他属性...
}

方案2:前端改造(适合后端无法修改的场景)

不使用浏览器默认的JSON.parse解析响应,改用支持大整数的解析库处理,以json-bigint为例:

  1. 安装依赖
npm install json-bigint
  1. 在Angular的HTTP拦截器中自定义响应解析逻辑,将超出精度的长整数转为字符串存储:
import { Injectable } from '@angular/core';
import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpResponse } from '@angular/common/http';
import JSONbig from 'json-bigint';
import { Observable, map } from 'rxjs';

@Injectable()
export class BigIntParseInterceptor implements HttpInterceptor {
  private jsonBig = JSONbig({ storeAsString: true });

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    return next.handle(req).pipe(
      map(event => {
        if (event instanceof HttpResponse && typeof event.body === 'string') {
          try {
            const parsedBody = this.jsonBig.parse(event.body);
            return event.clone({ body: parsedBody });
          } catch (e) {
            return event;
          }
        }
        return event;
      })
    );
  }
}
问题截图参考

后端响应
前端结果

内容的提问来源于stack exchange,提问作者Alonso Contreras

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 01:06:04