通过JSON发送64位值的可接受方式是什么?

时间:2008-10-16 19:13:17

标签: javascript json 64-bit

我的一些数据是64位整数。我想将这些发送到在页面上运行的JavaScript程序。

但是,据我所知,大多数JavaScript实现中的整数都是32位有符号数。

我的两个选择似乎是:

  1. 将值作为字符串发送
  2. 将值作为64位浮点数发送
  3. 选项(1)并不完美,但选项(2)似乎远不那么完美(数据丢失)。

    你是如何处理这种情况的?

6 个答案:

答案 0 :(得分:21)

这似乎不是JSON的问题,而是Javascript本身的问题。你打算用这些数字做什么?如果它只是一个魔术令牌,你需要稍后传回网站,一定只需使用包含该值的字符串。如果你真的必须对值进行算术运算,你可以编写自己的64位算术Javascript例程。

您可以在Javascript(以及JSON)中表示值的一种方法是将数字拆分为两个32位值,例如。

  [ 12345678, 12345678 ]

要将64位值拆分为两个32位值,请执行以下操作:

  output_values[0] = (input_value >> 32) & 0xffffffff;
  output_values[1] = input_value & 0xffffffff;

然后将两个32位值重新组合为64位值:

  input_value = ((int64_t) output_values[0]) << 32) | output_values[1];

答案 1 :(得分:7)

事实上,JavaScript / ECMAScript精度级别的限制为53位整数(它们存储在“双类”8字节内存缓冲区的尾数中)。因此,传输大数字作为JSON不会像JavaScript客户端那样按照预期进行反序列化,这会将它们截断为53位分辨率。

> parseInt("10765432100123456789")
10765432100123458000

请参阅Number.MAX_SAFE_INTEGER constantNumber.isSafeInteger()功能:

  

MAX_SAFE_INTEGER常量的值为9007199254740991。该   这个数字背后的推理是JavaScript使用双精度   IEEE 754中指定的浮点格式编号,只能   安全地表示-(2^53 - 1)2^53 - 1之间的数字。

     

此上下文中的安全是指表示整数的能力   准确地并且正确地比较它们。例如,   Number.MAX_SAFE_INTEGER + 1 === Number.MAX_SAFE_INTEGER + 2会   评估为true,这在数学上是不正确的。看到   Number.isSafeInteger()了解更多信息。

由于JavaScript中浮点数的分辨率,使用你提出的“64位浮点数”会受到同样的限制。

恕我直言,最好的选择是将这些值传输为文本。它仍然是完全可读的JSON内容,并且很容易在JavaScript级别上工作。

“纯字符串”表示是OData specifies, for its Edm.Int64 or Edm.Decimal types

在这种情况下,Twitter API的作用是在JSON中添加特定的".._str":字段,如下所示:

{
   "id": 10765432100123456789,           // for JSON compliant clients
   "id_str": "10765432100123456789",     // for JavaScript
    ...
}

我非常喜欢这个选项,因为它仍然可以与支持int64的客户端兼容。实际上,如果在HTTP级别对它进行缩小/压缩,那么JSON中的这种重复内容不会造成太大伤害。

一旦以字符串形式传输,您可以使用strint – a JavaScript library for string-encoded integers之类的库来处理这些值。

答案 2 :(得分:6)

Javascript的数字类型(64位IEEE 754)只有大约53位的精度。

但是,如果您不需要进行任何添加或乘法,那么您可以将64位值保持为4个字符的字符串,因为JavaScript使用UTF-16。

例如,1可以编码为“\ u0000 \ u0000 \ u0000 \ u0001”。这具有以下优点:值比较(==,&gt;,&lt;)按预期对字符串起作用。写位操作似乎也很简单:

function and64(a,b) {
    var r = "";
    for (var i = 0; i < 4; i++)
        r += String.fromCharCode(a.charCodeAt(i) & b.charCodeAt(i));
    return r;
}

答案 3 :(得分:2)

JS数字表示是标准的ieee double,因此您不能表示64位整数。你可以在一个double中获得48位实际int精度,但是所有JS bitop都降低到32位精度(这就是规范所要求的。是的!)所以如果你真的需要在js中使用64位int,你需要实现自己的64位int逻辑库。

答案 4 :(得分:0)

JSON本身并不关心实现限制。 你的问题是JS无法处理你的数据,而不是协议。 换句话说,您的JS客户端代码必须使用这些非完美选项中的任何一个。

答案 5 :(得分:0)

这件事发生在我身上。通过json将大整数发送到JSON.parse时,一切都变得一团糟。我花了几天时间尝试调试。当我将值作为字符串传输时,问题立即得到解决。

使用 { "the_sequence_number": "20200707105904535" } 代替 { "the_sequence_number": "20200707105904535" }

更糟糕的是,似乎实现每个JSON.parse的地方,都是Firefox,Chrome和Opera之间的共享库,因为它们的行为完全相同。 Opera错误消息中包含Chrome URL引用,就像浏览器共享的WebKit一样。

{ "the_sequence_number": 20200707105904535 }

我的行为是指针数学变得非常糟糕的那种东西。鬼魂从我的工作站飞出来,对我的睡眠造成了严重破坏。现在我切换到字符串,他们都被驱逐了。