有没有办法使用 bs-json 对大于 32 位的整数值进行编码?
Is there a way to encode integer values that are larger than 32 bits using bs-json?
我一直在使用字符串来表示解码后的 JSON 大于 32 位的整数。似乎 string_of_int
能够处理大整数输入。所以一个解码器,写成(在 Json.Decode 命名空间):
id: json |> field("id", int) |> string_of_int, /* 'id' is string */
正在成功处理至少 37 位的整数。
另一方面,事实证明编码对我来说很麻烦。远程服务器不接受字符串表示,并期待 int64。是否可以让 bs-json
支持 int64
类型?我希望这样的东西可以工作:
type myData = { id: int64 };
let encodeMyData = (data:myData) => Json.Encode.(object_([("id", int64(myData.id)]))
不得不推出自己的编码器并不像解码器那么可怕,但是......我宁愿不这样做。
你没有具体说出编码有什么问题。 int
编码器实际上除了改变类型什么都不做,相信 int
值实际上是有效的。所以我假设是 int_of_string
操作导致了问题。但这引出了一个问题,如果你能成功地将它解码为 int
,为什么还要将它转换为 string
?
这里的根本问题是 JavaScript 没有 64 位整数。 max safe integer is 253 - 1. JavaScript doesn't actually have integers at all, only float
s, which can represent a certain range of integers, but can't efficiently do integer arithmetic unless they're converted to either 32-bit or 64-bit int
s. And so for whatever reason, probably consistent overflow handling, it was decided in the EcmaScript specification 二进制按位运算应该对 32 位整数进行运算。因此,这为内部 32 位表示、创建 32 位整数的符号以及优化整数算法的可能性打开了可能性。
所以对于你的问题:
Would it be "safe" to just add external int64 : int64 -> Js.Json.t = "%identity" to the encoder files?
不,因为 JavaScript 中没有 64 位整数表示,int64
值表示为两个 Number
的数组,我相信,但这也是一个内部实现细节可能会发生变化。仅将其转换为 Js.Json.t
不会产生您期望的结果。
那么可以做什么呢?
我建议使用 float
。在大多数方面,这将与 JavaScript 数字完全一样,让您可以访问其全部范围。
或者您可以使用 nativeint
,它的行为应该类似于 float
s 除了除法,结果被截断为 32 位整数。
最后,您还可以实现自己的 int_of_string
,通过直接使用几个轻量级 JavaScript 函数来创建技术上超出范围的 int
,但我不会真的不推荐这样做:
let bad_int_of_string = str =>
str |> Js.Float.fromString |> Js.Math.floor_int;
我一直在使用字符串来表示解码后的 JSON 大于 32 位的整数。似乎 string_of_int
能够处理大整数输入。所以一个解码器,写成(在 Json.Decode 命名空间):
id: json |> field("id", int) |> string_of_int, /* 'id' is string */
正在成功处理至少 37 位的整数。
另一方面,事实证明编码对我来说很麻烦。远程服务器不接受字符串表示,并期待 int64。是否可以让 bs-json
支持 int64
类型?我希望这样的东西可以工作:
type myData = { id: int64 };
let encodeMyData = (data:myData) => Json.Encode.(object_([("id", int64(myData.id)]))
不得不推出自己的编码器并不像解码器那么可怕,但是......我宁愿不这样做。
你没有具体说出编码有什么问题。 int
编码器实际上除了改变类型什么都不做,相信 int
值实际上是有效的。所以我假设是 int_of_string
操作导致了问题。但这引出了一个问题,如果你能成功地将它解码为 int
,为什么还要将它转换为 string
?
这里的根本问题是 JavaScript 没有 64 位整数。 max safe integer is 253 - 1. JavaScript doesn't actually have integers at all, only float
s, which can represent a certain range of integers, but can't efficiently do integer arithmetic unless they're converted to either 32-bit or 64-bit int
s. And so for whatever reason, probably consistent overflow handling, it was decided in the EcmaScript specification 二进制按位运算应该对 32 位整数进行运算。因此,这为内部 32 位表示、创建 32 位整数的符号以及优化整数算法的可能性打开了可能性。
所以对于你的问题:
Would it be "safe" to just add external int64 : int64 -> Js.Json.t = "%identity" to the encoder files?
不,因为 JavaScript 中没有 64 位整数表示,int64
值表示为两个 Number
的数组,我相信,但这也是一个内部实现细节可能会发生变化。仅将其转换为 Js.Json.t
不会产生您期望的结果。
那么可以做什么呢?
我建议使用 float
。在大多数方面,这将与 JavaScript 数字完全一样,让您可以访问其全部范围。
或者您可以使用 nativeint
,它的行为应该类似于 float
s 除了除法,结果被截断为 32 位整数。
最后,您还可以实现自己的 int_of_string
,通过直接使用几个轻量级 JavaScript 函数来创建技术上超出范围的 int
,但我不会真的不推荐这样做:
let bad_int_of_string = str =>
str |> Js.Float.fromString |> Js.Math.floor_int;