你不知道的 JSON.stringfy

栏目: 后端 · 前端 · 发布时间: 4年前

内容简介:译者注:这篇文章已经被翻译过多次了,但是我觉得写的太好了,所以就再翻译一次吧,当作是加深印象。

http://thecodebarbarian.com/t...

写在前面

JSON.stringfy() 是将一个 JavaScript 对象转化为 JSON 格式字符串的 标准方式 。许多 JavaScript 框架在其内部,都会使用 JSON.stringify()Expressres.json()Axiospost ,以及 webpack stats ,它们都调用了 JSON.stringify() 方法,并包含错误案例。

译者注:这篇文章已经被翻译过多次了,但是我觉得写的太好了,所以就再翻译一次吧,当作是加深印象。

简单入门

所有的现代 JavaScript 运行时都支持 JSON.stringify() ,甚至 IE8 都支持它。下面是一个将简单对象转化为 JSON 的例子:

const obj = { answer: 42 };

const str = JSON.stringify(obj);
str; // '{"answer":42}'
typeof str; // 'string'

你可能经常看到 JSON.stringify()JSON.parse() 一起配合使用的场景,就像下面的代码一样,这种模式是实现 深拷贝 的方式之一:

const obj = { answer: 42 };
const clone = JSON.parse(JSON.stringify(obj));

clone.answer; // 42
clone === obj; // false

错误以及边界用例

JSON.stringify() 在转化对象存在循环引用时,会抛出 错误 。更简单地说,就是如果一个对象有一个属性指向它本身, JSON.stringify() 会抛出错误,比如:

const obj = {};
// 存在循环引用的对象,它指向它本身
obj.prop = obj;

// 会抛出 "TypeError: TypeError: Converting circular structure to JSON" 异常
JSON.stringify(obj);

这是 JSON.stringify() 会抛出异常的唯一情况,除非你通过声明自定义的 toJSON() 方法或者 replacer 函数。尽管如此,你仍然应该将 JSON.stringify() 包含在 try/catch 语句中,因为循环引用在实践中十分常见。

同时,一些边界用例下, JSON.stringify() 并不会抛出错误,但是你可能却期望它抛出错误。比如说, JSON.stringify() 会将 NaNInfinity 转化为 null :

const obj = { nan: parseInt('not a number'), inf: Number.POSITIVE_INFINITY };

JSON.stringify(obj); // '{"nan":null,"inf":null}'

JSON.stringify() 也会直接省略那些值为 functionsundefined 的属性,如下:

const obj = { fn: function() {}, undef: undefined };

// 它会返回空对象
JSON.stringify(obj); // '{}'

格式化

JSON.stringify() 的第一个参数是被序列化为 JSON 的对象。 JSON.stringify() 实际上可以接受 3 个参数,同时第三个参数被称作 spacesspaces 参数被用于采用一种可以提高可读性的方式来格式化 JSON 字符串。

你可以传递类型为 string 或者 numberspaces 参数。如果 spacesundefined ,那么 JSON.stringify() 会将每个键值放到单独的一行,同时为其增加正确的缩进空格,比如:

const obj = { a: 1, b: 2, c: 3, d: { e: 4 } };

// '{"a":1,"b":2,"c":3,"d":{"e":4}}'
JSON.stringify(obj);

// {
//   "a": 1,
//   "b": 2,
//   "c": 3,
//   "d": {
//     "e": 4
//   }
// }
JSON.stringify(obj, null, '  ');

// 数字 2 会达到和上面一样的效果,它代表空格的个数
JSON.stringify(obj, null, 2);

spaces 字符串不一定非要是空格,虽然通常我们会使用空格,比如它也可以是下划线:

// {
// __"a": 1,
// __"b": 2,
// __"c": 3,
// __"d": {
// ____"e": 4
// __}
// }
JSON.stringify(obj, null, '__');

Replacers

JSON.stringify() 的第二个参数是 replacer 函数。在上文的例子中,它等于 null 。JavaScript 会对对象中的每一个键值对调用 replacer 函数,然后会使用其返回值,作为格式化后的值,比如:

const obj = { a: 1, b: 2, c: 3, d: { e: 4 } };

// 使每个属性的值递增 1
// '{"a":2,"b":3,"c":4,"d":{"e":5}}'
JSON.stringify(obj, function replacer(key, value) {
  if (typeof value === 'number') {
    return value + 1;
  }
  return value;
});

replacer 函数在省略敏感数据时,十分有用。假设你想要省略所有包含 password 的属性:

const obj = {
  name: 'Jean-Luc Picard',
  password: 'stargazer',
  nested: {
    hashedPassword: 'c3RhcmdhemVy'
  }
};

// '{"name":"Jean-Luc Picard","nested":{}}'
JSON.stringify(obj, function replacer(key, value) {
  // 这个函数会被调用 5 次,这里的 key 依次为:
  // '', 'name', 'password', 'nested', 'hashedPassword'
  if (key.match(/password/i)) {
    return undefined;
  }
  return value;
});

toJSON 方法

JSON.stringify() 方法在遍历对象的同时,也会关注那些拥有 toJSON() 方法的属性。如果它发现 toJSON() 方法, JSON.stringify() 会调用它,然后将它的返回值替换格式化后的值,比如:

const obj = {
  name: 'Jean-Luc Picard',
  nested: {
    test: 'not in output',
    toJSON: () => 'test'
  }
};

// '{"name":"Jean-Luc Picard","nested":"test"}'
JSON.stringify(obj);

toJSON() 方法可以返回任意的值,包括对象、基础类型,或者 undefined 。如果 toJSON() 返回 undefinedJSON.stringify() 将会忽略这个属性。

很多 JavaScript 模块使用 toJSON() 来确保序列化复杂对象的正确性,比如 Mongoose documents Moment 对象

最后

JSON.stringify() 是 JavaScript 中较核心的基础方法。许多库和框架在其内部都使用它,因此,深入的理解它,可以帮助你更好地使用你喜欢的 npm 模块。比如,你可以在 Express REST API 中利用 toJSON 方法来格式化原生 Date 类型,或者在 Axios 中,能够正确地通过 HTTP 请求发送包含循环引用的对象。


以上所述就是小编给大家介绍的《你不知道的 JSON.stringfy》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Java5.0Tiger程序高手秘笈

Java5.0Tiger程序高手秘笈

BrettMclaughlin / 东南大学出版社 / 2005-10 / 28.00元

代号为 “Tiger”的下一个 Java 版本,不只是个小改动版。在语言核心中有超过 100 项以上的变动,同时有大量的对 library 与 API 所做的加强,让开发者取得许多新的功能、工具与技术。但在如此多的变化下,应该从何处开始着手?也许可以从既长又无趣的语言规范说明书开始看起;或等待最少 500 页的概念与理论巨著出版;甚至还可以直接把玩新的 JDK 看看能够有什么发现;或者借由《Jav......一起来看看 《Java5.0Tiger程序高手秘笈》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器