【问题标题】:alternative to JSON.parse() for maintaining decimal precision?替代 JSON.parse() 以保持小数精度?
【发布时间】:2017-12-21 00:18:11
【问题描述】:

我正在调用 JSON.parse() 来解析一个带有小数位的 JSON 字符串。

解析后未保持小数精度。例如,将返回像 3.1e-7 这样的值,而不是实际的小数。

如何在 ng2+ 中反序列化 JSON 字符串,同时保持小数精度?

更新

我正在考虑从字符串中映射出值,然后在 JSON.parse() 之后手动将值设置为对象,但是当我将不同的小十进制数字设置为属性值时,会出现相同的数字格式。那么这个问题不一定是 JSON.parse() 所特有的,而是一般的 Javascript 所特有的?还是 JSON.parse() 以某种固定方式配置属性类型?

【问题讨论】:

  • 实际小数是多少? JSON 对象是什么样的?
  • 请出示您的代码。 (var foo = JSON.parse('{"foo":0.000000315453}'); console.log(foo.foo) ... 给出“3.15453e-7”,但这可能因上下文而异
  • 例如,0.00000017 返回为 1.7e-7
  • 1.7e-70.00000017的实际表示

标签: javascript typescript


【解决方案1】:

一旦您通过 JSON.parse 传递您的 JSON 字符串,您就会因为 the way floating point math works 而失去精度。您需要将数字存储为object designed for storing arbitrary-precision numbers,并且您需要在解析字符串之前摆弄字符串本身。最简单的方法是使用正则表达式。 JSON 是一种上下文无关语法,正则表达式适用于常规语法,因此警告适用:

警告:使用正则表达式解析 CFG MAY SUMMON ZALGO

这个正则表达式应该将 JSON 中的数字转换为字符串:

let stringedJSON = origJSON.replace(/:\s*([-+Ee0-9.]+)/g, ': "uniqueprefix$1"');

但我没有对它进行广泛的测试,如果你有类似data:42 的键,它肯定会搞砸。

假设它工作正常,stringedJSON 现在应该类似于{"foo": "uniqueprefix0.00000017", "bar": "an actual string"}。您可以使用 JSON.parse 解析它而不会丢失精度,但 uniqueprefix0.00000017 不是您想要的。 JSON.parse 可以使用额外的 reviver 参数调用,该参数在返回之前转换传递给它的值。您可以使用它来将数据转换回有用的形式:

let o = JSON.parse(stringedJSON, (key, value) => {
  // only changing strings
  if (typeof value !== 'string') return value;
  // only changing number strings
  if (!value.startsWith('uniqueprefix')) return value;
  // chop off the prefix
  value = value.slice('uniqueprefix'.length);
  // pick your favorite arbitrary-precision library
  return new Big(value);
});

【讨论】:

  • 感谢“召唤 Zalgo”链接。让我早上好。
  • 正如您所提到的,该正则表达式匹配字符串中的数字,例如“data:42”。它也无法匹配任何不是对象值的数字(即数组值或顶级独立数字)。此正则表达式适用于任何 JSON 中的所有数字,并跳过作为字符串一部分的所有数字:replace( /((?:[^"]*?(?:"(?:[^"\\]|\\.)*?")?)*?)((?:[:,\[]|^)[\s\n]*)(-?(0|([1-9]\d*))(\.\d+)?([eE][-+]?\d*)?)/gsy, '$1$2"uniqueprefix$3"')
猜你喜欢
  • 2017-01-19
  • 2018-01-20
  • 2012-06-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-15
相关资源
最近更新 更多