JavaScript 中将实体对象转换为 JSON 字符串的实用指南**
在 JavaScript 开发中,我们经常需要将复杂的实体对象(即包含各种数据类型和嵌套结构的对象)转换为 JSON(JavaScript Object Notation)字符串,JSON 是一种轻量级的数据交换格式,易于人阅读和编写,也易于机器解析和生成,因此在前后端数据交互、配置文件存储等方面应用广泛,本文将详细介绍在 JavaScript 中如何将实体对象转换为 JSON 字符串,并探讨一些常见场景和注意事项。
核心方法:JSON.stringify()
JavaScript 提供了一个内置的全局对象 JSON,该对象包含一个核心方法 stringify(),专门用于将 JavaScript 值(通常是对象或数组)转换为 JSON 字符串。
基本语法
JSON.stringify(value[, replacer[, space]])
value: 要转换的 JavaScript 值,通常是对象或数组。replacer(可选): 一个函数或数组,用于转换或过滤结果。- 如果是函数,则每个属性都会经过该函数处理,返回值将作为该属性的值。
- 如果是数组,则只有数组中存在的键名才会被包含在最终的 JSON 字符串中。
space(可选): 一个用于美化输出 JSON 字符串的字符串或数字。- 如果是数字,表示缩进的空格数,最大为 10。
- 如果是字符串,则用该字符串作为缩进(最多前 10 个字符)。
- 不提供或为
null时,输出紧凑的 JSON 字符串(无多余空格和换行)。
基本示例
const user = {
id: 1,
name: "张三",
age: 30,
isStudent: false,
courses: ["JavaScript", "Node.js"],
address: {
city: "北京",
district: "朝阳区"
},
birthday: new Date('1993-05-20')
};
// 基本转换,输出紧凑的 JSON 字符串
const jsonString1 = JSON.stringify(user);
console.log(jsonString1);
// 输出: {"id":1,"name":"张三","age":30,"isStudent":false,"courses":["JavaScript","Node.js"],"address":{"city":"北京","district":"朝阳区"},"birthday":"1993-05-20T00:00:00.000Z"}
// 美化输出,使用 2 个空格缩进
const jsonString2 = JSON.stringify(user, null, 2);
console.log(jsonString2);
/*
输出:
{
"id": 1,
"name": "张三",
"age": 30,
"isStudent": false,
"courses": [
"JavaScript",
"Node.js"
],
"address": {
"city": "北京",
"district": "朝阳区"
},
"birthday": "1993-05-20T00:00:00.000Z"
}
*/
使用 replacer 函数进行自定义转换
replacer 函数允许我们在序列化过程中对每个属性进行控制,该函数接收两个参数:键名(key)和对应的值(value),然后返回一个经过处理的值,如果返回 undefined,则该属性会被忽略。
示例:过滤敏感信息或转换数据类型
const userWithSensitiveInfo = {
id: 1,
name: "李四",
password: "123456", // 敏感信息,不希望出现在 JSON 中
loginCount: 10,
lastLoginTime: new Date()
};
// 使用 replacer 函数过滤掉 password 属性,并将 loginCount 转换为字符串
const jsonStringWithReplacer = JSON.stringify(userWithSensitiveInfo, (key, value) => {
if (key === "password") {
return undefined; // 过滤掉 password
}
if (key === "loginCount") {
return `共登录${value}次`; // 转换为描述字符串
}
return value; // 其他属性保持不变
}, 2);
console.log(jsonStringWithReplacer);
/*
输出:
{
"id": 1,
"name": "李四",
"loginCount": "共登录10次",
"lastLoginTime": "2024-05-22T12:34:56.789Z" // 假设当前时间
}
*/
使用 replacer 数组指定包含的属性
如果只需要序列化对象中的特定属性,可以传递一个包含这些属性名的数组作为 replacer。
示例:只包含特定属性
const product = {
productId: "P001",
productName: "笔记本电脑",
price: 5999,
stock: 100,
description: "一款性能出色的轻薄笔记本"
};
// 只包含 productId, productName, price
const jsonStringWithArrayReplacer = JSON.stringify(product, ["productId", "productName", "price"]);
console.log(jsonStringWithArrayReplacer);
// 输出: {"productId":"P001","productName":"笔记本电脑","price":5999}
JSON.stringify() 的注意事项
-
循环引用: 如果对象中存在循环引用(即对象的某个属性通过引用链指向自身),
JSON.stringify()会抛出错误TypeError: Converting circular structure to JSON。const obj = {}; obj.self = obj; // 循环引用 // JSON.stringify(obj); // 抛出错误 -
不可枚举的属性:
JSON.stringify()会忽略对象中不可枚举的属性(使用Object.defineProperty定义且enumerable为false的属性)。 -
函数和 Symbol 类型: 对象中的函数和 Symbol 类型的属性会被自动忽略,不会出现在最终的 JSON 字符串中。
const data = { name: "王五", sayHello: function() { console.log("Hello"); }, }; console.log(JSON.stringify(data)); // 输出: {"name":"王五"} -
Date 对象: Date 对象会被转换为 ISO 8601 格式的字符串(
"2024-05-22T12:34:56.789Z")。 -
undefined、Infinity 和 NaN: 如果对象的值是
undefined、Infinity或NaN,它们会被转换为null。const specialValues = { a: undefined, b: Infinity, c: NaN, d: "正常值" }; console.log(JSON.stringify(specialValues)); // 输出: {"a":null,"b":null,"c":null,"d":"正常值"}
处理循环引用的替代方案
由于 JSON.stringify() 无法直接处理循环引用,如果确实需要处理包含循环引用的对象,可以考虑以下方法:
-
自定义序列化函数: 编写一个递归函数,手动遍历对象属性,并检测和处理循环引用,可以维护一个
Set来记录已经访问过的对象引用。function stringifyWithCircularRef(obj, indent = 2) { const cache = new Set(); function _stringify(obj) { if (obj && typeof obj === 'object') { if (cache.has(obj)) { return "[Circular Reference]"; } cache.add(obj); let output = Array.isArray(obj) ? '[' : '{'; const keys = Object.keys(obj); for (let i = 0; i < keys.length; i++) { const key = keys[i]; output += (Array.isArray(obj) ? '' : `"${key}":`) + _stringify(obj[key]); if (i < keys.length - 1) { output += ', '; } } output += Array.isArray(obj) ? ']' : '}'; cache.delete(obj); // 允许同一对象在不同路径被多次序列化,只要不是循环 return output; } return JSON.stringify(obj); } return JSON.parse(_stringify(obj)); // 为了确保格式正确,再解析一次,或者直接返回字符串 } const circularObj = { name: "循环" }; circularObj.self = circularObj; console.log(stringifyWithCircularRef(circularObj, 2)); /* 输出: { "name": "循环", "self": "[Circular Reference]" } */ -
使用第三方库: 一些第三方 JSON 库(如
flatted、cyclic等)提供了处理循环引用的序列化功能,这些库通常会有更健壮的实现。
将 JavaScript 实体对象转换为 JSON 字符串是前端开发中的常见操作。JSON.stringify() 方法提供了强大的功能,支持基本转换、



还没有评论,来说两句吧...