用于保持小数精度的JSON.parse()的替代品是什么?

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

在解析后,小数的精度没有得到保留。例如,一个像3.1e-7这样的值被返回而不是实际的小数。

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

更新

我考虑从字符串中映射出值,然后在JSON.parse()之后手动设置对象的值,但当我将另一个小小数作为属性值时,同样的数字格式化发生了。所以这个问题不一定是唯一的JSON.parse()问题,而是JavaScript通用的问题吗?或者JSON.parse()是否以某种固定的方式配置属性类型?


3
实际的十进制数是多少?这个JSON对象长什么样? - Hanlet Escaño
1
请展示你的代码。(例如:var foo = JSON.parse('{"foo":0.000000315453}'); console.log(foo.foo))... 返回结果可能因上下文不同而有所不同,但是通常会得到"3.15453e-7"。 - Tibrogargan
例如,0.00000017返回为1.7e-7。 - user8570495
3
"1.7e-7" 是表示 "0.00000017" 的实际值。 - zerkms
1
https://dev59.com/jXI-5IYBdhLWcg3wwbdM - Kaiido
显示剩余6条评论
1个回答

9
一旦您通过JSON.parse传递JSON字符串,由于浮点数的运算方式,您将失去精度。 您需要将数字存储为设计用于存储任意精度数字的对象,并且在解析之前需要调整字符串本身。 最简单的方法是使用正则表达式。 JSON是上下文无关文法,而正则表达式适用于正则文法,因此警告适用:

警告:使用正则表达式解析CFG 可能会召唤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);
});

感谢提供“召唤扎尔戈”链接。让我的早晨变得更加美好。 - Iskandar Reza
正如您所提到的,该正则表达式匹配像“data:42”这样的字符串中的数字。 它也无法匹配任何不是对象值的数字(例如数组值或独立顶级数字)。 此正则表达式将适用于JSON中的所有数字,并跳过作为字符串一部分的所有数字:replace( /((?:[^"]*?(?:"(?:[^"\\]|\\.)*?")?)*?)((?:[:,\[]|^)[\s\n]*)(-?(0|([1-9]\d*))(\.\d+)?([eE][-+]?\d*)?)/gsy, '$1$2"uniqueprefix$3"') - Paul

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接