JSON.parse()

Baseline 广泛可用 *

此特性已相当成熟,可在许多设备和浏览器版本上使用。自 ⁨2015 年 7 月⁩以来,各浏览器均已提供此特性。

* 此特性的某些部分可能存在不同级别的支持。

JSON.parse() 静态方法解析 JSON 字符串,构建该字符串所描述的 JavaScript 值或对象。可以选择提供一个可选的 reviver 函数,在返回结果对象之前对其进行转换。

试一试

const json = '{"result":true, "count":42}';
const obj = JSON.parse(json);

console.log(obj.count);
// Expected output: 42

console.log(obj.result);
// Expected output: true

语法

js
JSON.parse(text)
JSON.parse(text, reviver)

参数

文本

要解析为 JSON 的字符串。有关 JSON 语法的描述,请参阅 JSON 对象。

reviver 可选

如果是一个函数,它规定了从解析中原始生成的值在返回前如何进行转换。不可调用的值将被忽略。该函数使用以下参数调用:

key

与值关联的键。

value

通过解析产生的值。

context 可选

一个上下文对象,其中包含与当前正在恢复的表达式相关的状态。每次调用 reviver 函数时,它都是一个新对象。仅在恢复原始值时传递,当 value 是对象或数组时则不传递。它包含以下属性:

source

表示此值的原始 JSON 字符串。

返回值

与给定的 JSON text 对应的 ObjectArray、字符串、数字、布尔值或 null 值。

异常

SyntaxError

如果要解析的字符串不是有效的 JSON,则抛出此错误。

描述

JSON.parse() 按照 JSON 语法 解析 JSON 字符串,然后像 JavaScript 表达式一样计算该字符串。JSON 文本表示的值与相同的 JavaScript 表达式表示的值不同的唯一情况是处理 "__proto__" 键时 — 请参阅 对象字面量语法与 JSON

reviver 参数

如果指定了 reviver,则在返回解析计算出的值之前对其进行转换。具体来说,计算出的值及其所有属性(以 深度优先 方式,从最嵌套的属性开始,然后处理到原始值本身)将单独通过 reviver 进行处理。

reviver 使用包含正在处理的属性的对象作为 this 调用(除非您将 reviver 定义为箭头函数,在这种情况下没有单独的 this 绑定),并带有两个参数:keyvalue,分别代表属性名(字符串,即使是数组)和属性值。对于原始值,还会传递一个额外的 context 参数,其中包含此值的源文本。如果 reviver 函数返回 undefined(或不返回任何值 — 例如,如果执行结束于函数末尾),则该属性将从对象中删除。否则,该属性将被重新定义为返回值。如果 reviver 只转换某些值而不转换其他值,请务必将所有未转换的值原样返回 — 否则,它们将从结果对象中删除。

JSON.stringify()replacer 参数类似,对于数组和对象,reviver 最后一次被调用是在根值上,key 为空字符串,value 为根对象。对于其他有效的 JSON 值,reviver 的工作方式类似,并被调用一次,key 为空字符串,value 为值本身。

如果您从 reviver 返回另一个值,该值将完全替换原始解析的值。这甚至适用于根值。例如:

js
const transformedObj = JSON.parse('[1,5,{"s":1}]', (key, value) =>
  typeof value === "object" ? undefined : value,
);

console.log(transformedObj); // undefined

没有通用的方法可以解决这个问题。您无法专门处理 key 是空字符串的情况,因为 JSON 对象也可以包含空字符串作为键。实现 reviver 时,您需要非常精确地知道每个键需要哪种转换。

请注意,reviver 在值解析之后运行。因此,例如,JSON 文本中的数字将已经转换为 JavaScript 数字,并且在此过程中可能会丢失精度。一种在不丢失精度的情况下处理大数字的方法是将它们序列化为字符串,然后将它们恢复为 BigInts 或其他合适的任意精度格式。

您还可以使用 context.source 属性来访问表示该值的原始 JSON 源文本,如下所示:

js
const bigJSON = '{"gross_gdp": 12345678901234567890}';
const bigObj = JSON.parse(bigJSON, (key, value, context) => {
  if (key === "gross_gdp") {
    // Ignore the value because it has already lost precision
    return BigInt(context.source);
  }
  return value;
});

示例

使用 JSON.parse()

js
JSON.parse("{}"); // {}
JSON.parse("true"); // true
JSON.parse('"foo"'); // "foo"
JSON.parse('[1, 5, "false"]'); // [1, 5, "false"]
JSON.parse("null"); // null

使用 reviver 参数

js
JSON.parse(
  '{"p": 5}',
  (key, value) =>
    typeof value === "number"
      ? value * 2 // return value * 2 for numbers
      : value, // return everything else unchanged
);
// { p: 10 }

JSON.parse('{"1": 1, "2": 2, "3": {"4": 4, "5": {"6": 6}}}', (key, value) => {
  console.log(key);
  return value;
});
// 1
// 2
// 4
// 6
// 5
// 3
// ""

在与 JSON.stringify() 的 replacer 配对时使用 reviver

为了使一个值能够正确地进行往返(即,它被反序列化为与原始对象相同的对象),序列化过程必须保留类型信息。例如,您可以使用 JSON.stringify()replacer 参数来实现此目的:

js
// Maps are normally serialized as objects with no properties.
// We can use the replacer to specify the entries to be serialized.
const map = new Map([
  [1, "one"],
  [2, "two"],
  [3, "three"],
]);

const jsonText = JSON.stringify(map, (key, value) =>
  value instanceof Map ? Array.from(value.entries()) : value,
);

console.log(jsonText);
// [[1,"one"],[2,"two"],[3,"three"]]

const map2 = JSON.parse(jsonText, (key, value) =>
  Array.isArray(value) && value.every(Array.isArray) ? new Map(value) : value,
);

console.log(map2);
// Map { 1 => "one", 2 => "two", 3 => "three" }

因为 JSON 没有用于注解类型元数据的语法空间,为了恢复非纯对象的 JSON 值,您必须考虑以下几种方法之一:

  • 将整个对象序列化为字符串,并在前面加上类型标签。
  • 根据数据的结构进行“猜测”(例如,一个包含两个成员数组的数组)
  • 如果有效载荷的形状是固定的,则根据属性名进行(例如,所有名为 registry 的属性都包含 Map 对象)。

无效 JSON

JSON.parse 收到不符合 JSON 语法的字符串时,它会抛出 SyntaxError

JSON 中的数组和对象不能有尾部逗号

js
JSON.parse("[1, 2, 3, 4, ]");
// SyntaxError: Unexpected token ] in JSON at position 13

JSON.parse('{"foo": 1, }');
// SyntaxError: Unexpected token } in JSON at position 12

JSON 字符串必须用双引号(而不是单引号)分隔

js
JSON.parse("{'foo': 1}");
// SyntaxError: Unexpected token ' in JSON at position 1

JSON.parse("'string'");
// SyntaxError: Unexpected token ' in JSON at position 0

如果您在 JavaScript 字符串字面量中编写 JSON,您应该使用单引号分隔 JavaScript 字符串字面量,或者转义分隔 JSON 字符串的双引号。

js
JSON.parse('{"foo": 1}'); // OK
JSON.parse("{\"foo\": 1}"); // OK

规范

规范
ECMAScript® 2026 语言规范
# sec-json.parse

浏览器兼容性

另见