前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >[译] toJSON是个啥

[译] toJSON是个啥

作者头像
腾讯IVWEB团队
发布2020-06-28 00:14:27
1.3K0
发布2020-06-28 00:14:27
举报

在JavaScript中, JSON.stringify()方法会寻找被序列化对象的toJSON方法. 如果对象中存在toJSON方法, 那么JSON.stringify会用经toJSON方法序列化后的对象来序列化.

举一个例子, 下面的代码会打印出与JSON.stringify({ answer: 42})一样的内容

代码语言:javascript
复制
const json = JSON.stringify({
  answer: { toJSON: () => 42 }
});

console.log(json); // {"answer":42}

在ES6的class中

toJSON方法对于正确地序列化一个ES6的class具有很重要的意义. 举个例子, 假设你有一个自定的JavaScript的Error类

代码语言:javascript
复制
class HTTPError extends Error {
  constructor(message, status) {
    super(message);
    this.status = status;
  }
}

一般情况下, JavaScript对于错误的序列化并不是十分优秀. 下面的代码中会打印{"status": 404}, 没有错误信息也没有堆栈信息

代码语言:javascript
复制
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}

但是当你添加了一个toJSON方法在HTTPError类里面后, 你就可以控制JavaScript如何来序列化这个HTTPError的实例

代码语言:javascript
复制
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}

除此之外还能再整一些活来让toJSON方法在developmentNODE_ENV下额外带上堆栈信息

代码语言:javascript
复制
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实例

代码语言:javascript
复制
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方法

代码语言:javascript
复制
    function toJSON () {
        // JSON.stringify(new Date(NaN)) === 'null'
        return this.isValid() ? this.toISOString() : 'null';
    }

自己试一试的话可以试试这段代码

代码语言:javascript
复制
const moment = require('moment');
console.log(moment('2019-06-01').toJSON.toString());

Node.js的buffer也有这样的toJSON方法

代码语言:javascript
复制
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的文档也有toJSON方法来保证Mongoose文档的内部会状态不会跑到JSON.stringify的结果里面去

继续

toJSON方法在构建一个JavaScript类时是一个十分重要的工具. 这可以控制JavaScript类如何序列化为JSON. toJSON能够帮助开发者解决不少问题, 例如保证buffer能够正确地转化为正确地数据类型等. 下次写ES6的类时不妨试一试.

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 在ES6的class中
  • toJSON()的生态现状
  • 继续
相关产品与服务
文件存储
文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档