JavaScript操作JSON完全指南:从基础到高级应用
初识JSON:JavaScript中的数据交换格式
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,以易于阅读和编写的文本形式存储和传输数据,它基于JavaScript的一个子集,但已成为独立于语言的数据标准,在前后端数据交互中广泛应用,在JavaScript中,JSON与原生对象(Object)既有紧密联系,又有明确区别:JSON格式要求键必须用双引号包裹,值只能是字符串、数字、布尔值、null、数组或JSON对象,而JavaScript对象的键可以加单引号或双引号(甚至不加),值还可以是函数、undefined等类型,理解这一点是后续操作JSON的基础。
JavaScript解析JSON:字符串到对象的转换
前端开发中,常见的场景是将服务端返回的JSON字符串转换为JavaScript对象,以便在代码中操作数据,JavaScript提供了两种核心方法实现这一转换:JSON.parse()和eval()(不推荐)。
使用JSON.parse():安全且标准的方法
JSON.parse()是ES5引入的内置方法,专门用于将JSON格式的字符串解析为对应的JavaScript对象或值,它的语法简单,且具备安全性(不会执行字符串中的代码),是开发中的首选。
基础用法:
const jsonString = '{"name":"张三","age":25,"hobbies":["编程","阅读"]}';
const obj = JSON.parse(jsonString);
console.log(obj); // 输出:{name: "张三", age: 25, hobbies: ["编程", "阅读"]}
console.log(obj.name); // 输出:张三
处理嵌套JSON:
JSON支持嵌套结构,JSON.parse()会自动解析复杂层级:
const nestedJson = '{"user":{"id":1,"info":{"city":"北京","zip":100000}},"isVIP":true}';
const data = JSON.parse(nestedJson);
console.log(data.user.info.city); // 输出:北京
异常处理:
如果JSON字符串格式错误(如单引号包裹键、缺少引号、逗号使用不规范等),JSON.parse()会抛出SyntaxError,实际开发中需要配合try-catch使用:
const invalidJson = "{'name':'李四'}"; // 键使用单引号,格式错误
try {
const obj = JSON.parse(invalidJson);
console.log(obj);
} catch (error) {
console.error("JSON解析失败:", error.message); // 输出:JSON解析失败: Unexpected token ' in JSON
}
高级用法:reviver函数
JSON.parse()的第二个参数reviver是一个回调函数,允许在解析过程中对值进行转换或处理,将日期字符串转换为Date对象:
const jsonWithDate = '{"name":"王五","birth":"1990-01-01"}';
const data = JSON.parse(jsonWithDate, (key, value) => {
if (key === "birth") {
return new Date(value); // 将日期字符串转为Date对象
}
return value;
});
console.log(data.birth); // 输出:1990-01-01 00:00:00 (Date对象)
警惕eval():不推荐的危险方法
eval()是JavaScript的全局函数,可以执行字符串中的JavaScript代码,如果字符串是JSON格式,eval()也能将其转换为对象:
const jsonString = '{"name":"赵六","age":30}';
const obj = eval("(" + jsonString + ")"); // 需手动加括号,避免解析为代码块
console.log(obj.name); // 输出:赵六
为什么不推荐?
eval()会执行字符串中的任意代码,如果JSON字符串被恶意篡改(如注入alert("xss")),就会导致安全漏洞:
const maliciousJson = '{"name":"黑客","age":20,"evil":"alert(\'xss\')"}';
eval("(" + maliciousJson + ")").evil(); // 会弹出alert框,存在XSS风险
除非在绝对可控的环境下,否则严禁使用eval()解析JSON。
JavaScript序列化JSON:对象到字符串的转换
当前端需要将JavaScript对象发送给服务端时,需将其转换为JSON字符串,这一过程称为“序列化”,JavaScript提供了JSON.stringify()方法实现这一功能。
基础序列化:JSON.stringify()
JSON.stringify()将JavaScript对象或值转换为JSON格式的字符串,基本用法如下:
const obj = {
name: "钱七",
age: 28,
hobbies: ["游戏", "旅行"],
isStudent: false
};
const jsonString = JSON.stringify(obj);
console.log(jsonString);
// 输出:{"name":"钱七","age":28,"hobbies":["游戏","旅行"],"isStudent":false}
规则说明:
- 序列化时,JavaScript对象的键会被自动转换为双引号包裹的字符串(即使原键是未加引号的标识符)。
- 函数、
undefined、Symbol类型的值会被忽略(如果对象属性是这些类型,序列化后不会出现在字符串中)。 - 循环引用的对象会抛出
TypeError(见后文“高级用法”部分)。
高级序列化:replacer与space参数
JSON.stringify()支持第二个和第三个参数,实现更精细的控制。
(1)replacer:过滤或转换值
replacer可以是函数或数组,用于控制哪些属性被序列化,以及对属性值进行处理。
场景1:过滤敏感属性
序列化用户对象时隐藏密码:
const user = {
username: "admin",
password: "123456",
email: "admin@example.com"
};
// 使用数组指定需要序列化的属性名
const filteredStr1 = JSON.stringify(user, ["username", "email"]);
console.log(filteredStr1); // 输出:{"username":"admin","email":"admin@example.com"}
// 使用函数动态处理每个属性
const filteredStr2 = JSON.stringify(user, (key, value) => {
if (key === "password") {
return undefined; // 忽略password属性
}
return value;
});
console.log(filteredStr2); // 输出:{"username":"admin","email":"admin@example.com"}
场景2:转换值类型
将Date对象转换为时间戳字符串:
const data = {
name: "孙八",
createTime: new Date()
};
const str = JSON.stringify(data, (key, value) => {
if (value instanceof Date) {
return value.getTime(); // 转为时间戳
}
return value;
});
console.log(str); // 输出:{"name":"孙八","createTime":1678886400000}(时间戳根据实际日期变化)
(2)space:格式化输出字符串
space参数用于控制缩进和换行,使JSON字符串更易读(通常用于调试或日志输出),可以是数字(1-10,表示缩进空格数)或字符串(用字符串本身作为缩进):
const obj = {
name: "周九",
details: {
age: 35,
hobbies: ["摄影", "烹饪"]
}
};
// 数字缩进(2个空格)
const formattedStr1 = JSON.stringify(obj, null, 2);
console.log(formattedStr1);
/* 输出:
{
"name": "周九",
"details": {
"age": 35,
"hobbies": [
"摄影",
"烹饪"
]
}
}
*/
// 字符串缩进(使用"-> ")
const formattedStr2 = JSON.stringify(obj, null, "-> ");
console.log(formattedStr2);
/* 输出:
{
-> "name": "周九",
-> "details": {
-> -> "age": 35,
-> -> "hobbies": [
-> -> -> "摄影",
-> -> -> "烹饪"
-> -> ]
-> }
}
*/
注意事项:循环引用与特殊类型
循环引用问题:
如果对象存在循环引用(对象的某个属性指向自身),直接调用JSON.stringify()会抛出TypeError:
const obj = {};
obj.self = obj; // 循环引用
try {
JSON.stringify(obj); // 报错:TypeError: Converting circular structure to JSON
} catch (error) {
console.error(error.message);
}
解决方法:在序列化前手动处理循环引用,或使用第三方库(如flatted)。
特殊类型处理:
undefined、函数、Symbol:作为对象属性值时会被忽略,作为数组元素时会被转换为null。NaN、Infinity:会被转换为null。const specialObj = { func: function



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