【问题标题】:Is there a way to encode integer values that are larger than 32 bits using bs-json?有没有办法使用 bs-json 对大于 32 位的整数值进行编码?
【发布时间】:2021-03-15 16:24:56
【问题描述】:

我一直在使用字符串来表示大于 32 位的解码 JSON 整数。 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)]))

必须使用我自己的编码器并不像解码器那样强大,但是……我宁愿不要。

【问题讨论】:

  • @glennsl 将external int64 : int64 -> Js.Json.t = "%identity" 添加到编码器文件中是否“安全”?

标签: json reason bs-json


【解决方案1】:

您没有确切地说出编码有什么问题。 int 编码器实际上除了更改类型之外什么都不做,相信 int 值实际上是有效的。所以我认为是int_of_string 操作导致了问题。但这引出了一个问题,如果您可以成功将其解码为int,为什么还要将其转换为string

这里的根本问题是 JavaScript 没有 64 位整数。 max safe integer 是 253 - 1。JavaScript 实际上根本没有整数,只有 floats,可以表示一定范围的整数,但不能有效地进行整数运算除非它们被转换为 32 位或 64 位 ints。因此,无论出于何种原因,可能是一致的溢出处理,在EcmaScript specification 中决定二进制按位运算应该对 32 位整数进行操作。这为内部 32 位表示、创建 32 位整数的符号以及优化整数运算的可能性提供了可能性。

所以你的问题:

将外部 int64 : int64 -> Js.Json.t = "%identity" 添加到编码器文件中是否“安全”?

不,因为 JavaScript 中没有 64 位整数表示,int64 值表示为两个 Numbers 的数组,我相信,但它也是一个内部实现细节,可能会发生变化。仅将其转换为 Js.Json.t 不会产生您期望的结果。

那么可以做什么

我建议使用float。在大多数方面,它的行为与 JavaScript 数字完全一样,让您可以访问它的全部范围。

您也可以使用nativeint,它的行为应该类似于floats,除了除法,结果被截断为32位整数。

最后,您还可以实现自己的 int_of_string 来创建一个在技术上超出范围的 int,直接使用几个轻量级 JavaScript 函数,但我真的不建议这样做:

let bad_int_of_string = str => 
  str |> Js.Float.fromString |> Js.Math.floor_int;

【讨论】:

  • 这非常有用,谢谢。我知道在 JS 中,int 仅限于 IEEE-754 double 的显着性,似乎 string_of_int 处理 53(ish)位。不明白的是 Re 中的 int 似乎仅限于 32 位 - 至少就我的调查而言。我会试试你的建议。再次感谢您。
  • int 本身并不限于 32 位。它只是一个普通的 JavaScript Number 下面,实际上是一个 float。但是一些int 操作被限制为32位,可能是因为它们针对整数运算进行了优化。
  • nativeint + OCaml 文档允许我存储我需要的 37 位的 int,但在编译期间证明序列化很困难:Json.Encode.(object_([("id", int(myData.id)),])) 编译器在询问对于nativeint() 方法。使用我建议的int64 hack,不幸的是 - 正如您所预测的那样 - 将数字序列化为两个数组。您能否为序列化的最后一步提出策略?
  • 啊……非常感谢。使用浮点数(显然我没想到)有效。您的信息丰富且及时的回答使您的图书馆变得更好。
  • 乐于助人!!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-19
  • 1970-01-01
  • 1970-01-01
  • 2023-01-25
  • 1970-01-01
相关资源
最近更新 更多