自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

為什么JSON.parse會損壞大數(shù)字,如何解決這個問題?

開發(fā) 前端
JSON數(shù)據(jù)格式極其簡單,而且它是JavaScript的一個子集。所以它與JavaScript完全可以互換。你可以將一個JSON文檔粘貼到一個JavaScript文件中,這就是有效的JavaScript。

從10多年前JSON在線編輯器的早期開始,用戶經(jīng)常反映編輯器有時會破壞他們JSON文檔中的大數(shù)字的問題。直到現(xiàn)在,我們也沒能解決這個問題。在這篇文章中,我們深入解釋了這個問題,并展示如何在JSON Editor Online中解決這個問題。

大數(shù)字的問題

大多數(shù) Web 應(yīng)用程序處理來自服務(wù)器的數(shù)據(jù)。這些數(shù)據(jù)以純文本的JSON文檔形式被接收,并被解析成一個JavaScript對象或數(shù)組,這樣我們就可以讀取屬性并做一些事情。通常情況下,數(shù)據(jù)的解析是使用JSON.parse函數(shù)進行的,該函數(shù)內(nèi)置于JavaScript中,非??焖俸头奖恪?/p>

JSON數(shù)據(jù)格式極其簡單,而且它是JavaScript的一個子集。所以它與JavaScript完全可以互換。你可以將一個JSON文檔粘貼到一個JavaScript文件中,這就是有效的JavaScript。

在JavaScript中使用JSON應(yīng)該不會出現(xiàn)任何問題,但有一種棘手的情況可能會破壞數(shù)據(jù):大數(shù)字。這是一個有效的JSON字符串:

{"count": 9123372036854000123}

當我們將其解析為JavaScript并讀取 "count" 鍵時,我們會得到:

9123372036854000000

解析后的數(shù)值被破壞了:最后三位數(shù)字被重置為零。這是否是一個問題,取決于這些最后的數(shù)字是否確實有意義,但一般來說,知道這種情況可能會發(fā)生,可能會給你一種不舒服的感覺。

為什么大數(shù)字會被JSON.parse破壞?

像 9123372036854000123? 這樣的長數(shù)字既是有效的 JSON 也是有效的 JavaScript。當JavaScript 將數(shù)值解析為數(shù)字時,事情就出錯了。最初,JavaScript 只有一種數(shù)字類型。Number?。這是一個64位的浮點值,類似于C++、Java或C#中的Double值。這種浮點值可以存儲大約16位數(shù)字。因此,它不能完全代表像9123372036854000123這樣的數(shù)字,它有19位數(shù)字。在這種情況下,最后三位數(shù)字會丟失,破壞了該值。

在用浮點數(shù)存儲分數(shù)時也會發(fā)生同樣的情況:當你在 JavaScript 中計算 1/3時,結(jié)果是:

0.3333333333333333

在現(xiàn)實中,該值應(yīng)該有無限的小數(shù),但 JavaScript 的數(shù)字在大約 16位 之后就停止了。

那么,JSON文檔中像9123372036854000123?這樣的大數(shù)字是怎么來的呢?嗯,其他語言如Java或C#確實有其他數(shù)字數(shù)據(jù)類型,如Long。Long是一個64位的值,可以容納最多20位的整數(shù)。它能容納更多數(shù)字的原因是,它不需要像浮點值那樣存儲指數(shù)值。因此,在像Java這樣的語言中,你可以有一個Long值,它不能在JavaScript的Number類型中正確表示,或者在其他語言中的Double類型中正確表示。

JavaScript 的 Number(或者更好:任何浮點數(shù)值)還有一些限制:數(shù)值可以溢出或下溢。例如,1e+500?會變成Infinity?,而1e-500?會變成0。不過,這些限制在實際應(yīng)用程序中很少成為問題。

如何防止數(shù)字被 JSON.parse 破壞?

多年來,這個用 JavaScript 解析大數(shù)字的問題一直是https://jsoneditoronline.org/ 的用戶反復(fù)要求的。像大多數(shù)基于網(wǎng)絡(luò)的JSON編輯器一樣,它也使用了本地的JSON.parse函數(shù)和常規(guī)的JavaScript數(shù)字,所以它受到了上述的限制。

第一個想法可能是:等等,但是 JSON.parse? 有一個可選的reviver?參數(shù),允許你用不同的方式來解析內(nèi)容。但問題是,首先文本被解析成一個數(shù)字,接下來,它被傳遞給reviver。所以到那時,已經(jīng)太晚了,值已經(jīng)被破壞了。

為了解決這個問題,根本不能使用內(nèi)置的JSON.parse,必須使用一個不同的JSON解析器。對此有各種優(yōu)秀的解決方案:lossless-json、json-bigint、js-jon-bigint或json-source-map。

這些庫中的大多數(shù)都采取了務(wù)實的方法,將長數(shù)字直接解析為JavaScript相對較新的BigInt數(shù)據(jù)類型。lossless-json庫是專門為JSON Editor Online開發(fā)的。它采取了比JSON BigInt解決方案更加靈活和強大的方法。

默認情況下,lossless-json 將數(shù)字解析成一個輕量級的LosslessNumber?類,該類將數(shù)字值作為一個字符串持有。這保留了任何數(shù)值,甚至還保留了格式化,比如數(shù)值4.0?中的尾部零。當對其進行操作時,LosslessNumber?將被轉(zhuǎn)換為Number?或BigInt,或者在不安全時拋出一個錯誤。

該庫允許你傳遞你自己的數(shù)字解析器,所以你可以應(yīng)用你自己的策略來處理數(shù)字值。也許你想把長的數(shù)字值轉(zhuǎn)換成BigInt,或者把數(shù)值傳給某個BigNumber庫。你可以選擇是否要在數(shù)字信息丟失時拋出一個異常,或者默默地忽略某些類別的信息丟失。

因此,比較本地JSON.parse?函數(shù)和lossless-json,會得到以下結(jié)果:

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解析器是否能解決所有問題?

答案是并不能。這取決于你在解析數(shù)據(jù)后想做什么,但通常情況下,你想用它做一些事情。在屏幕上顯示數(shù)據(jù),驗證它,比較它,排序它,等等。例如,在JSON Editor Online中,你可以編輯數(shù)值,轉(zhuǎn)換文檔(查詢、過濾、排序等),比較兩個文檔,或者根據(jù)JSON模式驗證一個文檔。一旦你引入BigInt值或LosslessNumbers,你想執(zhí)行的所有操作都需要支持這些類型的值。

擁有 BigInt 值或 LosslessNumbers 的數(shù)據(jù)很可能給不了解這些數(shù)據(jù)類型的第三方庫帶來問題。例如,JSON Editor Online支持將你的JSON數(shù)據(jù)導(dǎo)出到CSV,并使用優(yōu)秀的json2csv庫來實現(xiàn)。

這個庫不知道BigInt?或LosslessNumber?類型,不會正確串聯(lián)這些數(shù)據(jù)類型。為了使其正常工作,包含LosslessNumbers?或BigInt值的JSON數(shù)據(jù)必須首先被轉(zhuǎn)換為該庫所能理解的數(shù)據(jù)。

即使沒有第三方庫的參與,與BigInt值一起工作也會導(dǎo)致棘手的問題。當對大整數(shù)和普通數(shù)字的混合操作時,JavaScript可以默默地將一種數(shù)字類型強制轉(zhuǎn)化為另一種,這可能會導(dǎo)致錯誤。下面的代碼例子顯示了這是如何出錯的。

const a = 91111111111111e3 // a regular number
const b = 91111111111111000n // a bigint
console.log(a == b) // returns false (should be true)
console.log(a > b) // returns true (should be false)

在這個例子中,你看到兩個常數(shù)??a???和??b???持有相同的數(shù)字值。但是一個是數(shù)字,另一個是BigInt,用這些東西和普通的操作符(如??==???和??>??)一起使用會導(dǎo)致錯誤的結(jié)果。

結(jié)論:要讓大數(shù)字在一個應(yīng)用程序中工作,可能需要大量的努力。因此,最好的辦法是盡量避免在一開始就處理這些問題。

如果你真的要處理大數(shù)值,你必須使用一個替代的JSON分析器,如??lossless-json???。為了防止陷入與擁有??BigInt???或??LosslessNumber??數(shù)據(jù)類型有關(guān)的難以調(diào)試的問題,使用TypeScript明確定義你的數(shù)據(jù)模型是很有幫助的。這樣,你就可以事先知道哪些地方需要能夠處理這些特殊的數(shù)據(jù)類型,你就可以采取行動,而不是讓你的應(yīng)用程序默默地失敗。

在線JSON編輯器現(xiàn)在可以安全地處理大數(shù)字了

從今天起,JSON Editor Online已經(jīng)完全支持大數(shù)字,所以你不必再擔心損壞的數(shù)值。它已經(jīng)集成了lossless-json庫,并確保編輯器的所有功能都能處理大數(shù)字:從格式化、排序和查詢到導(dǎo)出到CSV。作為一個副作用,它現(xiàn)在甚至保持了數(shù)字的格式化,而且由于新的LosslessJSON解析器,現(xiàn)在可以檢測到重復(fù)的鍵。

試一試:https://jsoneditoronline.org/#left=json.%7B%20%22using%22:%20%22Lossless%20JSON%20Parser%22,%20%22formatted%20number%22:%204.0,%20%22long%22:%209123372036854000123,%20%22large%22:%201e500,%20%22small%22:1e-500%20%7D

現(xiàn)在,使用lossless-json有一個缺點:它比原生內(nèi)置的JSON.parse慢得多。這只是大的JSON對象或數(shù)組的問題,對于大于10MB的文件,它可能會很明顯。為了仍能順利地處理大文件,JSON Editor Online允許你選擇你想使用的解析器,默認情況下,它會自動為你選擇最合適的解析器。

責任編輯:姜華 來源: 大遷世界
相關(guān)推薦

2013-08-01 10:05:54

大數(shù)據(jù)信息安全

2023-12-26 17:07:56

GenAICIO

2025-04-01 05:22:00

JavaThread變量

2017-07-20 07:30:16

大數(shù)據(jù)數(shù)據(jù)互聯(lián)網(wǎng)

2023-09-07 17:06:21

@Autowired報錯原因分析

2022-07-14 14:27:34

Javascript數(shù)字精度二進制

2020-03-16 10:56:06

大數(shù)據(jù)IT安全

2012-09-05 11:09:15

SELinux操作系統(tǒng)

2020-10-19 07:51:25

Linux軟件

2016-12-13 11:34:10

2024-01-04 12:53:00

Unicode字符UTF-8

2021-01-18 14:34:59

冪等性接口客戶端

2010-04-29 17:46:31

Oracle死鎖

2022-09-07 07:05:25

跨域問題安全架構(gòu)

2015-05-15 17:29:13

.Netxp系統(tǒng)如何解決

2023-04-19 14:20:49

2025-04-21 10:43:21

2023-02-15 07:03:41

跨域問題面試安全

2017-10-17 09:21:06

2023-10-30 18:35:47

MySQL主從延時
點贊
收藏

51CTO技術(shù)棧公眾號