JSON

Baseline 廣泛可用 *

此特性已相當成熟,可在許多裝置和瀏覽器版本上使用。自 ⁨2015 年 7 月⁩以來,各瀏覽器均已提供此特性。

* 此特性的某些部分可能存在不同級別的支援。

JSON 名稱空間物件包含用於解析 JavaScript 物件表示法 (JSON) (JSON) 中的值以及將值轉換為 JSON 的靜態方法。

描述

與大多數全域性物件不同,JSON 不是建構函式。您不能將其與 new 運算子 一起使用,也不能將 JSON 物件呼叫為函式。JSON 的所有屬性和方法都是靜態的(就像 Math 物件一樣)。

JavaScript 和 JSON 的區別

JSON 是一種用於序列化物件、陣列、數字、字串、布林值和 null 的語法。它基於 JavaScript 語法,但與 JavaScript 不同:大多數 JavaScript 不是 JSON。例如:

物件和陣列

屬性名必須是雙引號括起來的字串;尾部逗號 是禁止的。

數字

禁止前導零。小數點後必須至少跟一個數字。NaNInfinity 不受支援。

任何 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

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 物件。

js
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 或自定義庫)。

js
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 函式。

js
// 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 數字。

js
// 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 引數來自己重新解析數字。

js
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

瀏覽器相容性

另見