在 JavaScript 中,JSON.stringify()
函数会在被序列化的对象中查找名为 toJSON
的函数。如果一个对象有 toJSON
函数,JSON.stringify()
会调用 toJSON()
序列化 toJSON()
的返回值。
例如,下面的脚本打印的内容与 JSON.stringify({ answer: 42 })
相同:
const json = JSON.stringify({
answer: { toJSON: () => 42 }
});
console.log(json); // {"answer":42}
在 ES6 类中
toJSON()
函数对于确保 ES6 类被正确序列化非常有用。例如,假设您有一个自定义的 JavaScript 错误类:
class HTTPError extends Error {
constructor(message, status) {
super(message);
this.status = status;
}
}
默认情况下,JavaScript 并不擅长处理序列化错误。用下面的脚本打印 {"status":404}
,没有错误消息或堆栈跟踪。
class HTTPError extends Error {
constructor(message, status) {
super(message);
this.status = status;
}
}
const e = new HTTPError('Fail', 404);
console.log(JSON.stringify(e)); // {"status":404}
但是,如果你在 HTTPError
类中添加了 toJSON()
方法,你就可以配置 JavaScript 如何序列化 HTTPError
的实例。
class HTTPError extends Error {
constructor(message, status) {
super(message);
this.status = status;
}
toJSON() {
return { message: this.message, status: this.status };
}
}
const e = new HTTPError('Fail', 404);
console.log(JSON.stringify(e)); // {"message":"Fail","status":404}
如果 NODE_ENV
是 development
的,你甚至可以让 toJSON()
序列化堆栈跟踪。
class HTTPError extends Error {
constructor(message, status) {
super(message);
this.status = status;
}
toJSON() {
const ret = { message: this.message, status: this.status };
if (process.env.NODE_ENV === 'development') {
ret.stack = this.stack;
}
return ret;
}
}
const e = new HTTPError('Fail', 404);
// {"message":"Fail","status":404,"stack":"Error: Fail\n at ...
console.log(JSON.stringify(e));
toJSON()
的巧妙之处在于 JavaScript 会处理递归,因此它仍然能够正确地序列化深度嵌套的 HTTPError
实例和数组中的 HTTPError
实例。
class HTTPError extends Error {
constructor(message, status) {
super(message);
this.status = status;
}
toJSON() {
return { message: this.message, status: this.status };
}
}
const e = new HTTPError('Fail', 404);
// {"nested":{"message":"Fail","status":404},"arr":[{"message":"Fail","status":404}]}
console.log(JSON.stringify({
nested: e,
arr: [e]
}));
许多库和框架在底层使用 JSON.stringify()
。例如,Express 的 res.json()
函数和 Axios POST 请求使用 JSON.stringify()
将对象转换为 JSON。所以自定义 toJSON()
函数也可以使用这些模块。
不在类中的 toJSON()
许多 Node.js 库和框架使用 toJSON()
来确保 JSON.stringify()
能够将复杂的对象序列化成有意义的东西。例如,Moment.js 对象有一个简单的 toJSON()
函数,如下所示:
function toJSON () {
// JSON.stringify(new Date(NaN)) === 'null'
return this.isValid() ? this.toISOString() : 'null';
}
你可以自己运行试试看:
const moment = require('moment');
console.log(moment('2019-06-01').toJSON.toString());
Node.js buffers 也有一个 toJSON()
函数。
const buf = Buffer.from('abc');
console.log(buf.toJSON.toString());
// Prints:
function toJSON() {
if (this.length > 0) {
const data = new Array(this.length);
for (var i = 0; i < this.length; ++i)
data[i] = this[i];
return { type: 'Buffer', data };
} else {
return { type: 'Buffer', data: [] };
}
}
Mongoose documents 还有一个 toJSON()
函数,以确保 Mongoose documents 的内部状态不会出现在 JSON.stringify()
输出中。
继续
在 JavaScript 中构建类时,toJSON()
函数是一个重要的工具。它是你控制 JavaScript 如何将你的类序列化成 JSON 的方式。toJSON()
函数可以帮助你解决很多问题,比如确保日期或Node.js buffer 以正确的格式序列化你的应用程序。下次你写 ES6 类的时候可以试一试。
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!