JSON.parse()

JSON.parse() 静态方法分析 JSON 字符串,构造由字符串描述的 JavaScript 值或对象。可以提供可选的 reviver 函数,在返回结果对象之前对其执行转换。

试一试

语法

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

参数

text

要作为 JSON 分析的字符串。有关 JSON 语法的说明,请参阅 JSON 对象。

reviver 可选

如果为函数,则此函数规定在返回之前如何转换最初通过分析生成的每个值。不可调用的值将被忽略。该函数使用以下参数调用

key

与该值关联的键。

value

通过分析生成的值。

context 可选

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

source

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

返回值

对应于给定 JSON textObjectArray、字符串、数字、布尔值或 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 transformedObj1 = JSON.parse('[1,5,{"s":1}]', (key, value) => {
  return typeof value === "object" ? undefined : value;
});

console.log(transformedObj1); // 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
// ""

将 reviver 与 JSON.stringify() 的 replacer 配合使用

为了使值能够正确往返(即,它被反序列化为相同的原始对象),序列化过程必须保留类型信息。例如,您可以为此目的使用 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) ? new Map(value) : value,
);

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

由于 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 语言规范
# sec-json.parse

浏览器兼容性

BCD 表格仅在启用 JavaScript 的浏览器中加载。

另请参阅