我一直在使用字符串来表示大于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)]))
必须滚动我自己的编码器并不像解码器那么可怕,但是。。。我宁愿不要。
您没有确切说明编码有什么问题。int
编码器除了更改类型之外什么也不做,因为它相信int
值实际上是有效的。所以我认为是int_of_string
操作造成了问题。但这就引出了一个问题,如果你能成功地将其解码为int
,为什么要将其转换为string
?
这里的根本问题是JavaScript没有64位整数。最大安全整数是253-1。JavaScript实际上根本没有整数,只有float
s,它可以表示一定范围的整数,但除非将它们转换为32位或64位的int
s,否则无法有效地进行整数运算。因此,无论出于何种原因,可能是一致的溢出处理,在EcmaScript规范中决定二进制逐位操作应当对32位整数进行操作。因此,这开启了内部32位表示的可能性,创建32位整数的符号,以及优化整数运算的可能性。
因此,对于您的问题:
它会是"安全";只添加外部int64:int64->Js。Json.t="%"身份;到编码器文件?
不,因为JavaScript中没有64位整数表示,所以int64
值表示为两个Number
的数组,我相信这也是一个可能更改的内部实现细节。仅仅将其强制转换为Js.Json.t
不会产生您期望的结果。
那么你能做什么?
我建议使用float
。在大多数方面,这将表现得与JavaScript数字完全一样,让您可以访问其全部范围。
或者,您可以使用nativeint
,它的行为应该与float
s类似,除了除法,除法的结果被截断为32位整数。
最后,您还可以直接使用几个轻量级JavaScript函数来实现自己的int_of_string
,以创建一个技术上超出范围的int
,尽管我不建议这样做:
let bad_int_of_string = str =>
str |> Js.Float.fromString |> Js.Math.floor_int;