为什么在.NET Web API JSON响应有效载荷中,长类型在16位后被四舍五入?

问题描述 投票:-3回答:2

我正在使用web api 2,我巧合地意识到它将长类型四舍五入。long 类型的值,如果它是长于16位数,在响应模型。

(为了问题的需要,简化了这个例子)假设我有一个web api方法为 "GetOrders",它返回订单模型列表,定义如下。

public class OrderVm{
    public int OrderID {get;set;}
    public long? OrderNumber {get;set;}
}

现在的情况是,如果我的订单号的值是:

  • 1234567890123459 没有问题 - 总共16位数字。
  • 1234567890123499 没有问题--共16位数字。
  • 12345678901234599 这是有问题的。 总共17位数字。这是四舍五入到 12345678901234600

下面是我简化的API方法示例。

        [HttpPost]
        [Route("get-orders/")]
        public IHttpActionResult GetOrders(PostedVm postedVm)
        {
              var orderDtoList = _orderManager.GetOrders(postedVm.Active); // I checked the value in orderDtoList and it is not rounded at this moment...
              var orderVmList  = MapDtoToVm(orderDtoList);    
              return Ok(orderVmList);// I thought maybe something happens during the property mapping (which is just using simple reflection) but I checked the value in orderVmList and it is not rounded at this moment...
        }

尽管在返回响应之前,我检查了一下... 实际上,这些值并不是四舍五入的。 但不知何故在客户端,它是作为四舍五入的。我想也许是浏览器做了一些魔法(出于某种原因),但我在postman和fiddler上检查了我的payload,它显示在响应payload中的值是四舍五入的,这听起来和web api配置有关,但如果是这样,我如何设置它不修改数据?

这听起来和web api配置有关,但如果是这样的话,我怎样才能设置它不修改数据?而且我也很好奇 "为什么在16位数字之后会出现这种情况?"

为了以防万一,我在下面添加了我的WebApiConfig类。

 public static class WebApiConfig {
    public static void Register(HttpConfiguration config) {
        //GZip Compression
        GlobalConfiguration.Configuration.MessageHandlers.Insert(0, new ServerCompressionHandler(new GZipCompressor(), new DeflateCompressor()));

        // Web API routes
        config.MapHttpAttributeRoutes();
        config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));

        config.Routes.MapHttpRoute(
        name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new {
            id = RouteParameter.Optional
        });
    }
}
c# asp.net-web-api asp.net-web-api2
2个回答
0
投票

这很可能是由于数字表示为IEEE 754 (double 在C#中)。)

由于二进制表示法,可能会有四舍五入的情况,所以 1234567890123459912345678901234600 具有相同的二进制表示。

你可以在C#中也观察到这种行为。

double x = 12345678901234599;
double y = 12345678901234600;
Console.WriteLine(x == y); // Prints true

https:/dotnetfiddle.netG0KOqZ

EDIT:尽管我最初的回答是JSON标准没有规定数字限制,但问题是一样的。

该规范允许实现者对接受的数字范围和精度进行限制。 由于实现IEEE754二进制64(双精度)数字[IEEE754]的软件普遍存在并被广泛使用,因此,实现者可以通过期望不超过这些提供的精度和范围来实现良好的互操作性,也就是说,实现者会在预期的精度范围内近似于JSON数字。

https:/tools.ietf.orghtmlrfc8259#section-6


0
投票

谢谢 Guy Incognito 他指给我看JSON的原始响应。在原始响应中,我的值没有四舍五入。但是,在原始响应中,我的值没有被四舍五入。当我解析JSON的时候,这个数字对JavaScript来说太大了,而且浮点数字的精度不是无限的我也有这个问题。我最后把我的数据类型改为 string 因为无论如何我都不会用它做任何算术运算。

感谢 Guy Incognito 再次。这个职位 也是很有帮助的。

© www.soinside.com 2019 - 2024. All rights reserved.