返回

揭秘JSON.stringify()和JSON.parse()隐藏的陷阱

前端

JSON.stringify() 和 JSON.parse():深入了解 JavaScript 的 JSON 操作 API

理解 JSON.stringify()

JSON.stringify() 是一个强大的 JavaScript API,可将对象转换为 JSON 字符串。然而,它并不是完全直观的。

想象一下您有一个包含姓名、年龄和工作函数的对象。您可能认为 JSON.stringify() 会将对象的所有属性转换为字符串,但事实并非如此。它只转换具有 toJSON() 方法的属性,其他属性会被忽略。

const obj = {
  name: "John Doe",
  age: 30,
  job: () => "Software Engineer",
  symbol: Symbol("secret")
};

const jsonStr = JSON.stringify(obj);
console.log(jsonStr); // {"name":"John Doe","age":30}

示例中,jobsymbol 属性被忽略了。

JSON.stringify() 中的 toJSON() 方法

toJSON() 是一个特殊的函数,允许您自定义对象转换为 JSON 字符串的方式。当 JSON.stringify() 遇到具有 toJSON() 方法的对象时,它将使用该方法返回的值作为对象的 JSON 表示。

const obj = {
  name: "John Doe",
  age: 30,
  toJSON: function() {
    return {
      name: this.name,
      age: this.age,
      salary: this.salary * 2
    };
  }
};

const jsonStr = JSON.stringify(obj);
console.log(jsonStr); // {"name":"John Doe","age":30,"salary":20000}

在示例中,toJSON() 方法将 salary 属性的值乘以 2,并将其添加到返回的对象中。

理解 JSON.parse()

JSON.parse() 用于从 JSON 字符串中解析数据。虽然通常很方便,但在某些情况下它可能会遇到问题。

如果 JSON 字符串包含无效的 JSON 数据或循环引用,JSON.parse() 可能会失败。

// 无效的 JSON 字符串
const jsonStr1 = "{name: "John Doe"}";

// 包含循环引用的 JSON 字符串
const obj = {
  name: "John Doe",
  age: 30,
  self: obj
};
const jsonStr2 = JSON.stringify(obj);

try {
  const obj1 = JSON.parse(jsonStr1);
  console.log(obj1); // SyntaxError: Unexpected token n in JSON at position 1
} catch (err) {
  console.error(err);
}

try {
  const obj2 = JSON.parse(jsonStr2);
  console.log(obj2); // TypeError: Converting circular structure to JSON
} catch (err) {
  console.error(err);
}

示例中,jsonStr1 是无效的 JSON 字符串,jsonStr2 包含循环引用,导致 JSON.parse() 失败。

避免 JSON.stringify() 和 JSON.parse() 陷阱的技巧

  • 确保对象的所有属性都具有 toJSON() 方法,或者使用 replacer 参数指定要转换的属性。
  • 在解析 JSON 字符串之前,请确保它是有效的,并且不包含循环引用。
  • 小心处理日期、正则表达式和函数等特殊类型的数据。

常见问题解答

  • 为什么我的对象属性在 JSON.stringify() 中被忽略了?
    可能是因为这些属性没有 toJSON() 方法。
  • 如何将函数转换为 JSON 字符串?
    您可以使用 JSON.stringify()replacer 参数或自定义 toJSON() 方法。
  • 为什么 JSON.parse() 抛出一个错误?
    JSON 字符串可能无效或包含循环引用。
  • 如何避免 JSON.stringify() 中的循环引用?
    使用 toJSON() 方法来过滤循环引用或使用 replacer 参数来跳过它们。
  • JSON.stringify() 和 JSON.parse() 可以转换所有类型的 JavaScript 数据吗?
    否,它们无法转换函数、符号和循环引用。