【问题标题】:How to serialize 64-bit integer in JavaScript?如何在 JavaScript 中序列化 64 位整数?
【发布时间】:2020-03-25 03:30:49
【问题描述】:

Datadog Tracing API 需要序列化为 JSON 数字的 64 位整数。

{
  "span_id": 16956440953342013954,
  "trace_id": 13756071592735822010
}

如何使用 JavaScript 创建带有 64 位整数的 JSON?

【问题讨论】:

  • 我认为你必须使用 Uint8Array 或 DataView

标签: javascript json integer


【解决方案1】:

这实际上比看起来要困难得多。

在 JavaScript 中表示大整数可以使用 BigInt 数据类型(通过使用 n 为数字添加后缀)来完成,这在这一点上得到了相当广泛的支持。

这将使您的对象看起来像这样:

const o = {
  span_id: 16956440953342013954n,
  trace_id: 13756071592735822010n
};

问题出现在 JSON 序列化中,因为目前不支持BigInt 对象的序列化。而在 JSON 序列化方面,您的自定义选项非常有限:

  • 可与JSON.stringify() 一起使用的replacer 函数可让您自定义BigInt 对象的序列化行为,但不允许您将它们序列化为原始(未加引号的)字符串。
  • 出于同样的原因,在BigInt 原型上实现toJSON() 方法也将不起作用。
  • 由于 JSON.stringify() 似乎不会在内部递归调用自身,因此涉及将其包装在 proxy 中的解决方案也不起作用。

所以我能找到的唯一选择是(至少部分地)实现您自己的 JSON 序列化机制。

这是一个非常穷人的实现,它为BigInt 类型的对象属性调用toString(),否则委托给JSON.stringify()

const o = {
  "span_id": 16956440953342013954n,
  "trace_id": 13756071592735822010n
};

const stringify = (o) => '{'
  + Object.entries(o).reduce((a, [k, v]) => ([
      ...a, 
      `"${k}": ${typeof v === 'bigint' ? v.toString() : JSON.stringify(v)}`
    ])).join(', ')
  + '}';

console.log(stringify(o));

请注意,上述方法在许多情况下都无法正常工作,最突出的是嵌套对象和数组。如果我要在实际使用中这样做,我可能会以Douglas Crockford's JSON implementation 为基础。在this line 周围添加一个额外的案例就足够了:

case "bigint":
  return value.toString();

【讨论】:

  • 太奇怪了,JavaScript Object Notation API 很难使用......来自 JavaScript。但这是 2020 年。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-02-28
  • 2020-07-06
  • 2019-04-05
  • 2017-07-22
  • 2017-05-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多