微信搜寻 【大迁世界】, 我会第一工夫和你分享前端行业趋势,学习路径等等。
本文 GitHub https://github.com/qq449245884/xiaozhi 已收录,有一线大厂面试残缺考点、材料以及我的系列文章。
从10多年前JSON在线编辑器的晚期开始,用户常常反映编辑器有时会毁坏他们JSON文档中的大数字的问题。直到现在,咱们也没能解决这个问题。在这篇文章中,咱们深刻解释了这个问题,并展现如何在JSON Editor Online中解决这个问题。
大数字的问题
大多数 Web 利用程序处理来自服务器的数据。这些数据以纯文本的JSON文档模式被接管,并被解析成一个JavaScript对象或数组,这样咱们就能够读取属性并做一些事件。通常状况下,数据的解析是应用JSON.parse
函数进行的,该函数内置于JavaScript中,十分疾速和不便。
JSON数据格式极其简略,而且它是JavaScript的一个子集。所以它与JavaScript齐全能够调换。你能够将一个JSON文档粘贴到一个JavaScript文件中,这就是无效的JavaScript。
在JavaScript中应用JSON
应该不会呈现任何问题,但有一种辣手的状况可能会毁坏数据:大数字。这是一个无效的JSON字符串:
{"count": 9123372036854000123}
当咱们将其解析为JavaScript并读取 "count"
键时,咱们会失去:
9123372036854000000
解析后的数值被毁坏了:最初三位数字被重置为零。这是否是一个问题,取决于这些最初的数字是否的确有意义,但一般来说,晓得这种状况可能会产生,可能会给你一种不难受的感觉。
为什么大数字会被JSON.parse毁坏?
像 9123372036854000123
这样的长数字既是无效的 JSON 也是无效的 JavaScript。当JavaScript 将数值解析为数字时,事件就出错了。最后,JavaScript 只有一种数字类型。Number
。这是一个64位的浮点值,相似于C++、Java或C#中的Double值。这种浮点值能够存储大概16位数字。因而,它不能齐全代表像9123372036854000123
这样的数字,它有19位数字。在这种状况下,最初三位数字会失落,毁坏了该值。
在用浮点数存储分数时也会产生同样的状况:当你在 JavaScript 中计算 1/3
时,后果是:
0.3333333333333333
在事实中,该值应该有有限的小数,但 JavaScript 的数字在大概 16位 之后就进行了。
那么,JSON文档中像9123372036854000123
这样的大数字是怎么来的呢?嗯,其余语言如Java或C#的确有其余数字数据类型,如Long。Long是一个64
位的值,能够包容最多20位的整数。它能包容更多数字的起因是,它不须要像浮点值那样存储指数值。因而,在像Java这样的语言中,你能够有一个Long值,它不能在JavaScript的Number类型中正确示意,或者在其余语言中的Double类型中正确示意。
JavaScript 的 Number(或者更好:任何浮点数值)还有一些限度:数值能够溢出或下溢。例如,1e+500
会变成Infinity
,而1e-500
会变成0
。不过,这些限度在理论应用程序中很少成为问题。
如何避免数字被 JSON.parse 毁坏?
多年来,这个用 JavaScript 解析大数字的问题始终是https://jsoneditoronline.org/
的用户重复要求的。像大多数基于网络的JSON编辑器一样,它也应用了本地的JSON.parse函数和惯例的JavaScript数字,所以它受到了上述的限度。
第一个想法可能是:等等,然而 JSON.parse
有一个可选的reviver
参数,容许你用不同的形式来解析内容。但问题是,首先文本被解析成一个数字,接下来,它被传递给reviver
。所以到那时,曾经太晚了,值曾经被毁坏了。
为了解决这个问题,基本不能应用内置的JSON.parse
,必须应用一个不同的JSON解析器。对此有各种优良的解决方案:lossless-json、json-bigint、js-jon-bigint或json-source-map。
这些库中的大多数都采取了求实的办法,将长数字间接解析为JavaScript绝对较新的BigInt数据类型。lossless-json
库是专门为JSON Editor Online开发的。它采取了比JSON BigInt解决方案更加灵便和弱小的办法。
默认状况下,lossless-json 将数字解析成一个轻量级的LosslessNumber
类,该类将数字值作为一个字符串持有。这保留了任何数值,甚至还保留了格式化,比方数值4.0
中的尾部零。当对其进行操作时,LosslessNumber
将被转换为Number
或BigInt
,或者在不平安时抛出一个谬误。
该库容许你传递你本人的数字解析器,所以你能够利用你本人的策略来解决数字值。兴许你想把长的数字值转换成BigInt,或者把数值传给某个BigNumber
库。你能够抉择是否要在数字信息失落时抛出一个异样,或者默默地疏忽某些类别的信息失落。
因而,比拟本地JSON.parse
函数和lossless-json
,会失去以下后果:
import { parse, stringify } from 'lossless-json'const text = '{"decimal":2.370,"long":9123372036854000123,"big":2.3e+500}'// JSON.parse will lose some digits and a whole number:console.log(JSON.stringify(JSON.parse(text)))// '{"decimal":2.37,"long":9123372036854000000,"big":null}'// WHOOPS!!!// LosslessJSON.parse will preserve all numbers and even the formatting:console.log(stringify(parse(text)))// '{"decimal":2.370,"long":9123372036854000123,"big":2.3e+500}'
应用LosslessJSON解析器是否能解决所有问题?
答案是并不能。这取决于你在解析数据后想做什么,但通常状况下,你想用它做一些事件。在屏幕上显示数据,验证它,比拟它,排序它,等等。例如,在JSON Editor Online中,你能够编辑数值,转换文档(查问、过滤、排序等),比拟两个文档,或者依据JSON模式验证一个文档。一旦你引入BigInt值或LosslessNumbers,你想执行的所有操作都须要反对这些类型的值。
领有 BigInt 值或 LosslessNumbers 的数据很可能给不理解这些数据类型的第三方库带来问题。例如,JSON Editor Online反对将你的JSON数据导出到CSV,并应用优良的json2csv库来实现。
这个库不晓得BigInt
或LosslessNumber
类型,不会正确串联这些数据类型。为了使其失常工作,蕴含LosslessNumbers
或BigInt
值的JSON数据必须首先被转换为该库所能了解的数据。
即便没有第三方库的参加,与BigInt值一起工作也会导致辣手的问题。当对大整数和一般数字的混合操作时,JavaScript能够默默地将一种数字类型强制转化为另一种,这可能会导致谬误。上面的代码例子显示了这是如何出错的。
const a = 91111111111111e3 // a regular numberconst b = 91111111111111000n // a bigintconsole.log(a == b) // returns false (should be true)console.log(a > b) // returns true (should be false)
在这个例子中,你看到两个常数a
和b
持有雷同的数字值。然而一个是数字,另一个是BigInt,用这些货色和一般的操作符(如==
和>
)一起应用会导致谬误的后果。
论断:要让大数字在一个应用程序中工作,可能须要大量的致力。因而,最好的方法是尽量避免在一开始就解决这些问题。
如果你真的要解决大数值,你必须应用一个代替的JSON分析器,如lossless-json
。为了避免陷入与领有BigInt
或LosslessNumber
数据类型无关的难以调试的问题,应用TypeScript明确定义你的数据模型是很有帮忙的。这样,你就能够当时晓得哪些地方须要可能解决这些非凡的数据类型,你就能够采取行动,而不是让你的应用程序默默地失败。
在线JSON编辑器当初能够平安地解决大数字了
从今天起,JSON Editor Online曾经齐全反对大数字,所以你不用再放心损坏的数值。它曾经集成了lossless-json
库,并确保编辑器的所有性能都能解决大数字:从格式化、排序和查问到导出到CSV。作为一个副作用,它当初甚至放弃了数字的格式化,而且因为新的LosslessJSON
解析器,当初能够检测到反复的键。
试一试:https://jsoneditoronline.org/...,%20%22formatted%20number%22:%204.0,%20%22long%22:%209123372036854000123,%20%22large%22:%201e500,%20%22small%22:1e-500%20%7D
当初,应用lossless-json
有一个毛病:它比原生内置的JSON.parse
慢得多。这只是大的JSON对象或数组的问题,对于大于10MB的文件,它可能会很显著。为了仍能顺利地解决大文件,JSON Editor Online容许你抉择你想应用的解析器,默认状况下,它会主动为你抉择最合适的解析器。
代码部署后可能存在的BUG没法实时晓得,预先为了解决这些BUG,花了大量的工夫进行log 调试,这边顺便给大家举荐一个好用的BUG监控工具 Fundebug。
起源:https://jsoneditoronline.org/...
交换
有幻想,有干货,微信搜寻 【大迁世界】 关注这个在凌晨还在刷碗的刷碗智。
本文 GitHub https://github.com/qq449245884/xiaozhi 已收录,有一线大厂面试残缺考点、材料以及我的系列文章。