JavaScript JSON:解析和字符串化数据
JavaScript 中 JSON 的完整指南。学习 JSON.parse()、JSON.stringify()、错误处理和 Web 开发的高级技术。
Big JSON Team
• Technical WriterExpert in JSON data manipulation, API development, and web technologies. Passionate about creating tools that make developers' lives easier.
# JavaScript JSON:解析和字符串化数据
JavaScript 通过 JSON 全局对象提供原生 JSON 支持,具有两个主要方法:JSON.parse() 和 JSON.stringify()。本指南涵盖了在 Web 开发中使用 JSON 所需的一切。
JavaScript 中的 JSON
JSON 对象提供了在 JSON 格式和 JavaScript 值之间转换的方法。它是 ECMAScript 5 的一部分,在所有现代浏览器中都可用。
主要方法
- JSON.parse():将 JSON 字符串解析为 JavaScript 对象
- JSON.stringify():将 JavaScript 值转换为 JSON 字符串
JSON.parse() - 解析 JSON 字符串
将 JSON 字符串转换为 JavaScript 对象:
基本用法
const jsonString = '{"name": "张三", "age": 30, "city": "北京"}';
const obj = JSON.parse(jsonString);
console.log(obj.name); // "张三"
console.log(obj.age); // 30
console.log(obj.city); // "北京"
解析数组
const arrayString = '[1, 2, 3, 4, 5]';
const numbers = JSON.parse(arrayString);
console.log(numbers[0]); // 1
console.log(numbers.length); // 5
解析嵌套对象
const jsonString = '{
"user": {
"name": "李四",
"address": {
"city": "上海",
"district": "浦东"
}
}
}';
const data = JSON.parse(jsonString);
console.log(data.user.address.city); // "上海"
解析布尔值和 null
const jsonString = '{"active": true, "deleted": false, "value": null}';
const obj = JSON.parse(jsonString);
console.log(obj.active); // true
console.log(obj.deleted); // false
console.log(obj.value); // null
JSON.stringify() - 转换为 JSON
将 JavaScript 对象转换为 JSON 字符串:
基本用法
const user = {
name: "王五",
age: 25,
active: true,
city: "广州"
};
const json = JSON.stringify(user);
console.log(json);
// {"name":"王五","age":25,"active":true,"city":"广州"}
美化输出
使用第三个参数添加缩进:
const formatted = JSON.stringify(user, null, 2);
console.log(formatted);
// {
// "name": "王五",
// "age": 25,
// "active": true,
// "city": "广州"
// }
// 使用 4 空格缩进
const formatted4 = JSON.stringify(user, null, 4);
// 使用制表符
const formattedTab = JSON.stringify(user, null, '\t');
字符串化数组
const colors = ["红色", "绿色", "蓝色"];
const json = JSON.stringify(colors);
console.log(json); // ["红色","绿色","蓝色"]
字符串化嵌套对象
const company = {
name: "科技创新",
employees: [
{ name: "张三", role: "开发者" },
{ name: "李四", role: "设计师" }
],
active: true
};
const json = JSON.stringify(company, null, 2);
console.log(json);
替换器和复活器函数
替换器 - 过滤属性
使用替换器函数控制序列化:
const data = {
name: "张三",
password: "secret123",
age: 30,
email: "zhangsan@example.com"
};
// 过滤敏感数据
const json = JSON.stringify(data, (key, value) => {
if (key === "password") return undefined;
return value;
});
console.log(json);
// {"name":"张三","age":30,"email":"zhangsan@example.com"}
替换器数组
只包含指定的属性:
const user = {
name: "李四",
age: 28,
password: "secret",
email: "lisi@example.com"
};
const json = JSON.stringify(user, ["name", "email"]);
console.log(json);
// {"name":"李四","email":"lisi@example.com"}
复活器 - 转换值
使用复活器函数转换解析的值:
const jsonString = '{"date":"2026-01-15T00:00:00Z","count":"42"}';
const obj = JSON.parse(jsonString, (key, value) => {
// 将日期字符串转换为 Date 对象
if (key === "date") {
return new Date(value);
}
// 将数字字符串转换为数字
if (key === "count") {
return parseInt(value);
}
return value;
});
console.log(obj.date instanceof Date); // true
console.log(typeof obj.count); // "number"
高级复活器示例
const jsonString = '{
"created": "2026-01-15T10:30:00Z",
"modified": "2026-01-15T14:20:00Z",
"price": "99.99"
}';
const obj = JSON.parse(jsonString, (key, value) => {
// 自动转换所有日期字段
if (typeof value === "string" && /^\d{4}-\d{2}-\d{2}T/.test(value)) {
return new Date(value);
}
// 转换价格
if (key === "price") {
return parseFloat(value);
}
return value;
});
console.log(obj);
错误处理
捕获解析错误
const invalidJson = '{"name": "张三", "age": 30,}'; // 尾随逗号
try {
const obj = JSON.parse(invalidJson);
} catch (error) {
console.error("JSON 解析错误:", error.message);
// JSON 解析错误:Unexpected token } in JSON at position 26
}
安全的 JSON 解析
创建一个安全的解析器函数:
function safeJSONParse(jsonString, fallback = null) {
try {
return JSON.parse(jsonString);
} catch (error) {
console.error("无法解析 JSON:", error.message);
return fallback;
}
}
// 使用
const result = safeJSONParse('invalid json', {});
console.log(result); // {}
验证 JSON
function isValidJSON(str) {
try {
JSON.parse(str);
return true;
} catch (e) {
return false;
}
}
console.log(isValidJSON('{"name":"张三"}')); // true
console.log(isValidJSON('{name: "张三"}')); // false(单引号)
console.log(isValidJSON('{"name":"张三",}')); // false(尾随逗号)
数据类型映射
JavaScript 到 JSON
| JavaScript 类型 | JSON 表示 |
|----------------|----------|
| Object | object |
| Array | array |
| String | string |
| Number | number |
| Boolean | true/false |
| null | null |
| undefined | 省略 |
| Function | 省略 |
| Symbol | 省略 |
| Date | 字符串(需要 toJSON) |
特殊值处理
const data = {
name: "张三",
age: 30,
active: true,
deleted: false,
value: null,
undefined: undefined, // 将被省略
fn: function() {}, // 将被省略
date: new Date() // 转换为 ISO 字符串
};
console.log(JSON.stringify(data));
// {"name":"张三","age":30,"active":true,"deleted":false,"value":null,"date":"2026-01-15T..."}
实际示例
示例 1:本地存储
// 保存到 localStorage
const user = {
name: "张三",
preferences: {
theme: "dark",
language: "zh"
}
};
localStorage.setItem('user', JSON.stringify(user));
// 从 localStorage 读取
const savedUser = JSON.parse(localStorage.getItem('user'));
console.log(savedUser.preferences.theme); // "dark"
示例 2:Fetch API
// 发送 JSON 数据
const postData = async () => {
const data = {
username: "zhangsan",
email: "zhangsan@example.com"
};
const response = await fetch('https://api.example.com/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
const result = await response.json(); // 自动解析 JSON
console.log(result);
};
示例 3:深度克隆
// 简单的深度克隆(有限制)
const original = {
name: "张三",
address: {
city: "北京",
district: "朝阳"
},
hobbies: ["阅读", "编程"]
};
const clone = JSON.parse(JSON.stringify(original));
// 修改克隆不会影响原始对象
clone.address.city = "上海";
console.log(original.address.city); // "北京"
console.log(clone.address.city); // "上海"
注意:这种方法有限制:
- 丢失函数
- 丢失 undefined 值
- 日期转换为字符串
- 不处理循环引用
示例 4:表单数据序列化
// 表单数据到 JSON
const form = document.querySelector('form');
const formData = new FormData(form);
const data = Object.fromEntries(formData);
const json = JSON.stringify(data);
// 发送到服务器
fetch('/api/submit', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: json
});
示例 5:配置管理
class ConfigManager {
constructor() {
this.config = this.load();
}
load() {
const saved = localStorage.getItem('app-config');
return saved ? JSON.parse(saved) : this.getDefaults();
}
save() {
localStorage.setItem('app-config', JSON.stringify(this.config));
}
get(key) {
return this.config[key];
}
set(key, value) {
this.config[key] = value;
this.save();
}
getDefaults() {
return {
theme: 'light',
language: 'zh',
notifications: true
};
}
}
// 使用
const config = new ConfigManager();
config.set('theme', 'dark');
console.log(config.get('theme')); // "dark"
性能优化
避免重复解析
// 不好:重复解析
for (let i = 0; i < 1000; i++) {
const obj = JSON.parse(jsonString);
process(obj);
}
// 好:解析一次
const obj = JSON.parse(jsonString);
for (let i = 0; i < 1000; i++) {
process(obj);
}
大对象处理
// 对于非常大的对象,考虑分块处理
function processLargeJSON(jsonString) {
try {
const data = JSON.parse(jsonString);
// 分块处理
const chunkSize = 100;
for (let i = 0; i < data.length; i += chunkSize) {
const chunk = data.slice(i, i + chunkSize);
processChunk(chunk);
}
} catch (error) {
console.error("处理失败:", error);
}
}
常见陷阱
1. 循环引用
const obj = { name: "张三" };
obj.self = obj; // 循环引用
try {
JSON.stringify(obj);
} catch (error) {
console.error(error); // TypeError: Converting circular structure to JSON
}
// 解决方案:使用替换器
const seen = new WeakSet();
const json = JSON.stringify(obj, (key, value) => {
if (typeof value === "object" && value !== null) {
if (seen.has(value)) {
return;
}
seen.add(value);
}
return value;
});
2. 日期处理
const data = {
name: "事件",
date: new Date("2026-01-15")
};
// Date 转换为 ISO 字符串
const json = JSON.stringify(data);
console.log(json);
// {"name":"事件","date":"2026-01-15T00:00:00.000Z"}
// 解析回来是字符串,不是 Date
const parsed = JSON.parse(json);
console.log(typeof parsed.date); // "string"
// 解决方案:使用复活器
const restored = JSON.parse(json, (key, value) => {
if (key === "date") return new Date(value);
return value;
});
console.log(restored.date instanceof Date); // true
3. NaN 和 Infinity
const data = {
nan: NaN,
infinity: Infinity,
negInfinity: -Infinity
};
console.log(JSON.stringify(data));
// {"nan":null,"infinity":null,"negInfinity":null}
4. undefined vs null
const data = {
value1: null,
value2: undefined
};
console.log(JSON.stringify(data));
// {"value1":null}
// value2 被省略
最佳实践
1. 始终处理错误
function parseJSON(str) {
try {
return JSON.parse(str);
} catch (error) {
console.error("JSON 解析失败:", error.message);
return null;
}
}
2. 验证 API 响应
async function fetchData(url) {
const response = await fetch(url);
if (!response.ok) {
throw new Error(HTTP 错误!状态:${response.status});
}
const data = await response.json();
// 验证数据结构
if (!data || typeof data !== 'object') {
throw new Error('无效的响应数据');
}
return data;
}
3. 使用 TypeScript 进行类型安全
interface User {
name: string;
age: number;
email: string;
}
function parseUser(jsonString: string): User | null {
try {
const data = JSON.parse(jsonString);
// 运行时验证
if (!data.name || !data.age || !data.email) {
throw new Error('缺少必需字段');
}
return data as User;
} catch (error) {
console.error('解析用户失败:', error);
return null;
}
}
4. 格式化用于调试
console.log('调试数据:', JSON.stringify(data, null, 2));
5. 压缩用于生产
// 开发
const devJSON = JSON.stringify(data, null, 2);
// 生产
const prodJSON = JSON.stringify(data);
浏览器兼容性
JSON 对象在所有现代浏览器中都支持:
- ✅ Chrome 3+
- ✅ Firefox 3.5+
- ✅ Safari 4+
- ✅ Edge(所有版本)
- ✅ IE 8+
对于旧浏览器,可以使用 polyfill:
<script src="https://cdn.jsdelivr.net/npm/json3@3.3.3/lib/json3.min.js"></script>
结论
JavaScript 的原生 JSON 支持使得处理 JSON 数据变得简单高效。通过掌握 JSON.parse() 和 JSON.stringify(),以及它们的高级功能,您可以:
- ✅ 轻松解析和生成 JSON 数据
- ✅ 处理复杂的数据结构
- ✅ 实现自定义序列化和反序列化
- ✅ 安全地处理错误
- ✅ 优化性能
关键要点
JSON.parse() 将 JSON 字符串转换为对象JSON.stringify() 将对象转换为 JSON通过这些技术,您已准备好在 JavaScript 应用程序中自信地使用 JSON!