描述
與大多數全域性物件不同,JSON 不是建構函式。您不能將其與 new 運算子 一起使用,也不能將 JSON 物件呼叫為函式。JSON 的所有屬性和方法都是靜態的(就像 Math 物件一樣)。
JavaScript 和 JSON 的區別
JSON 是一種用於序列化物件、陣列、數字、字串、布林值和 null 的語法。它基於 JavaScript 語法,但與 JavaScript 不同:大多數 JavaScript 不是 JSON。例如:
任何 JSON 文字在 JSON 超集修訂之後都是有效的 JavaScript 表示式。在此修訂之前,U+2028 LINE SEPARATOR 和 U+2029 PARAGRAPH SEPARATOR 允許在 JSON 的字串字面量和屬性鍵中使用;但在 JavaScript 字串字面量中相同的使用會導致 SyntaxError。
其他區別包括只允許雙引號括起來的字串,並且不支援 undefined 或註釋。對於那些希望使用更易於人類閱讀的、基於 JSON 的配置格式的人來說,有 JSON5(由 Babel 編譯器使用)以及更常用的 YAML。
相同的文字在 JavaScript 物件字面量與 JSON 中的表示可能會有所不同。有關更多資訊,請參閱 物件字面量語法與 JSON。
完整的 JSON 語法
有效的 JSON 語法由以下 ABNF(擴充巴科斯-瑙爾正規化)形式定義的,並從 IETF JSON 標準 (RFC) 複製而來。
JSON-text = object / array
begin-array = ws %x5B ws ; [ left square bracket
begin-object = ws %x7B ws ; { left curly bracket
end-array = ws %x5D ws ; ] right square bracket
end-object = ws %x7D ws ; } right curly bracket
name-separator = ws %x3A ws ; : colon
value-separator = ws %x2C ws ; , comma
ws = *(
%x20 / ; Space
%x09 / ; Horizontal tab
%x0A / ; Line feed or New line
%x0D ; Carriage return
)
value = false / null / true / object / array / number / string
false = %x66.61.6c.73.65 ; false
null = %x6e.75.6c.6c ; null
true = %x74.72.75.65 ; true
object = begin-object [ member *( value-separator member ) ]
end-object
member = string name-separator value
array = begin-array [ value *( value-separator value ) ] end-array
number = [ minus ] int [ frac ] [ exp ]
decimal-point = %x2E ; .
digit1-9 = %x31-39 ; 1-9
e = %x65 / %x45 ; e E
exp = e [ minus / plus ] 1*DIGIT
frac = decimal-point 1*DIGIT
int = zero / ( digit1-9 *DIGIT )
minus = %x2D ; -
plus = %x2B ; +
zero = %x30 ; 0
string = quotation-mark *char quotation-mark
char = unescaped /
escape (
%x22 / ; " quotation mark U+0022
%x5C / ; \ reverse solidus U+005C
%x2F / ; / solidus U+002F
%x62 / ; b backspace U+0008
%x66 / ; f form feed U+000C
%x6E / ; n line feed U+000A
%x72 / ; r carriage return U+000D
%x74 / ; t tab U+0009
%x75 4HEXDIG ) ; uXXXX U+XXXX
escape = %x5C ; \
quotation-mark = %x22 ; "
unescaped = %x20-21 / %x23-5B / %x5D-10FFFF
HEXDIG = DIGIT / %x41-46 / %x61-66 ; 0-9, A-F, or a-f
; HEXDIG equivalent to HEXDIG rule in [RFC5234]
DIGIT = %x30-39 ; 0-9
; DIGIT equivalent to DIGIT rule in [RFC5234]
無意義的 空格 可以在任何地方出現,但不能出現在 JSONNumber(數字不能包含空格)或 JSONString(其中空格被解釋為字串中的相應字元,否則會導致錯誤)內部。製表符 (U+0009)、回車符 (U+000D)、換行符 (U+000A) 和空格 (U+0020) 是唯一有效的空格字元。
靜態屬性
JSON[Symbol.toStringTag]-
[Symbol.toStringTag]屬性的初始值為字串"JSON"。此屬性用於Object.prototype.toString()。
靜態方法
JSON.isRawJSON()-
測試一個值是否為
JSON.rawJSON()返回的物件。 JSON.parse()-
解析一段字串文字作為 JSON,可選地轉換生成的 P 值及其屬性,然後返回該值。
JSON.rawJSON()-
建立一個包含一段 JSON 文字的“原始 JSON”物件。序列化為 JSON 時,原始 JSON 物件被視為已經是 JSON 片段。此文字必須是有效的 JSON。
JSON.stringify()-
返回與指定值對應的 JSON 字串,可選地只包含特定屬性或以使用者定義的方式替換屬性值。
示例
示例 JSON
{
"browsers": {
"firefox": {
"name": "Firefox",
"pref_url": "about:config",
"releases": {
"1": {
"release_date": "2004-11-09",
"status": "retired",
"engine": "Gecko",
"engine_version": "1.7"
}
}
}
}
}
您可以使用 JSON.parse() 方法將上面的 JSON 字串轉換為 JavaScript 物件。
const jsonText = `{
"browsers": {
"firefox": {
"name": "Firefox",
"pref_url": "about:config",
"releases": {
"1": {
"release_date": "2004-11-09",
"status": "retired",
"engine": "Gecko",
"engine_version": "1.7"
}
}
}
}
}`;
console.log(JSON.parse(jsonText));
無損數字序列化
JSON 可以包含任意精度的數字文字。但是,由於 JavaScript 使用具有固定精度的浮點表示,因此不可能在 JavaScript 中精確表示所有 JSON 數字。例如,在 JavaScript 中 12345678901234567890 === 12345678901234567000,因為它們具有相同的浮點表示。這意味著沒有一個 JavaScript 數字能夠精確對應 12345678901234567890 這個 JSON 數字。
假設您有一個數字的精確表示(透過 BigInt 或自定義庫)。
const data = {
// Using a BigInt here to store the exact value,
// but it can also be a custom high-precision number library,
// if the number might not be an integer.
gross_gdp: 12345678901234567890n,
};
您想將其序列化,然後解析回相同的精確數字。這存在幾個困難:
- 在序列化方面,為了在 JSON 中獲得一個數字,您必須將一個數字傳遞給
JSON.stringify,無論是透過replacer函式還是透過toJSON方法。但在任何一種情況下,您在數字轉換時已經丟失了精度。如果您將字串傳遞給JSON.stringify,它將被序列化為字串,而不是數字。 - 在解析方面,並非所有數字都能被精確表示。例如,
JSON.parse("12345678901234567890")返回12345678901234568000,因為該數字被四捨五入到最接近的可表示數字。即使您使用reviver函式,數字在呼叫reviver函式之前就已經被四捨五入了。
通常有兩種方法可以確保數字被無損地轉換為 JSON 並解析回來:一種涉及 JSON 數字,另一種涉及 JSON 字串。JSON 是一個通訊格式,因此如果您使用 JSON,您很可能是在與其他系統通訊(HTTP 請求、儲存在資料庫中等)。最佳解決方案取決於接收方系統。
使用 JSON 字串
如果接收方系統沒有與 JavaScript 相同的 JSON 處理能力,並且不支援高精度數字,您可能希望將數字序列化為字串,然後在接收方將其作為字串處理。在舊版 JavaScript 中,這也是唯一的選項。
要指定自定義資料型別(包括 BigInt)如何序列化為 JSON,請向您的資料型別新增一個 toJSON 方法,或者使用 JSON.stringify() 的 replacer 函式。
// Using toJSON() method
BigInt.prototype.toJSON = function () {
return this.toString();
};
const str1 = JSON.stringify(data);
// Using JSON.stringify() with replacer
const str2 = JSON.stringify(data, (key, value) => {
if (key === "gross_gdp") {
return value.toString();
}
return value;
});
在這兩種情況下,JSON 文字看起來都將是 {"gross_gdp":"12345678901234567890"},其中值是字串,而不是數字。然後,在接收方,您可以解析 JSON 並處理該字串。
使用 JSON 數字
如果訊息的接收方原生支援高精度數字(例如 Python 整數),則將數字作為 JSON 數字傳遞顯然更好,因為它們可以直接解析為高精度型別,而不是從 JSON 解析字串,然後再從字串解析數字。在 JavaScript 中,您可以透過使用 JSON.rawJSON() 來精確指定 JSON 源文字應該是怎樣的,從而在不先產生數字值(導致精度丟失)的情況下將任意資料型別序列化為 JSON 數字。
// Using toJSON() method
BigInt.prototype.toJSON = function () {
return JSON.rawJSON(this.toString());
};
const str1 = JSON.stringify(data);
// Using JSON.stringify() with replacer
const str2 = JSON.stringify(data, (key, value) => {
if (key === "gross_gdp") {
return JSON.rawJSON(value.toString());
}
return value;
});
傳遞給 JSON.rawJSON 的文字被視為已經是 JSON 片段,因此不會再次被序列化為字串。因此,JSON 文字看起來將是 {"gross_gdp":12345678901234567890},其中值是數字。前提是接收方系統沒有與 JavaScript 相同的精度限制,此 JSON 就可以被接收方直接解析,無需額外處理。
在 JavaScript 中解析包含高精度數字的 JSON 時,請格外小心,因為當 JSON.parse() 呼叫 reviver 函式時,您收到的值已經經過解析(並且已經丟失了精度)。您可以使用 JSON.parse() 的 reviver 函式中的 context.source 引數來自己重新解析數字。
const parsedData = JSON.parse(str, (key, value, context) => {
if (key === "gross_gdp") {
// Or use the constructor of your custom high-precision number library
return BigInt(context.source);
}
return value;
});
// { gross_gdp: 12345678901234567890n }
規範
| 規範 |
|---|
| ECMAScript® 2026 語言規範 # sec-json-object |
瀏覽器相容性
載入中…