json.stringify() 会自动调用对象的 tojson() 方法并用其返回值参与序列化;该方法可定义在对象自身或原型链上,返回任意类型值(undefined 在对象中被忽略、数组中转为 null),用于控制序列化输出格式。

JavaScript 中,当使用 JSON.stringify() 序列化一个对象时,如果该对象定义了 toJSON() 方法,引擎会自动调用它,并用其返回值代替原对象参与序列化过程。这是标准规范支持的机制,无需额外配置。
toJSON 方法的基本行为
toJSON() 是一个约定方法(非强制接口),只要对象自身或其原型链上有这个方法,且是可调用函数,JSON.stringify() 就会在处理该对象时优先调用它,然后将返回值继续递归序列化。
- 返回值可以是任意类型(包括
null、基本类型、普通对象、数组等) - 若返回
undefined,该属性会被忽略(在对象中)或转为null(在数组中) -
toJSON()不影响对象本身的结构或行为,仅作用于 JSON 序列化环节
在自定义类中定义 toJSON
常见做法是在类的原型或实例上添加 toJSON 方法,控制对外暴露的数据格式:
class User {
constructor(name, email, password) {
this.name = name;
this.email = email;
this.password = password;
}
toJSON() {
// 过滤敏感字段,只保留需要序列化的属性
return {
name: this.name,
email: this.email
// password 被排除
};
}
}
const user = new User("Alice", "alice@example.com", "secret123");
console.log(JSON.stringify(user));
// → {"name":"Alice","email":"alice@example.com"}
toJSON 的调用时机与嵌套处理
toJSON() 会在任何层级被触发——无论是顶层对象,还是作为属性值、数组元素、嵌套子对象出现:
- 如果对象 A 的某个属性值是对象 B,而 B 有
toJSON(),则 B 的该方法会被调用 - 数组中包含自定义对象,也会逐个触发其
toJSON() - 即使
toJSON()返回另一个带toJSON()的对象,也会继续递归调用
例如:
const obj = {
id: 1,
data: new User("Bob", "bob@test.com", "xxx"),
tags: [new User("TagUser", "t@x.com", "y")]
};
console.log(JSON.stringify(obj));
// → {"id":1,"data":{"name":"Bob","email":"bob@test.com"},"tags":[{"name":"TagUser","email":"t@x.com"}]}
注意事项与常见陷阱
实际使用中需注意几点:
-
toJSON()必须是**自有属性或原型上的方法**;通过Object.defineProperty设置时要确保enumerable: true(默认为false,会导致不生效) - 不能用箭头函数定义
toJSON(会丢失this绑定) - 避免在
toJSON()中修改原始对象状态(比如删除属性、重置字段),这会影响后续逻辑 - 如果返回值本身又含
toJSON方法(如返回另一个自定义实例),会继续触发,需防止无限递归
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











