JavaScript JSON
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成。JSON 在现代 Web 开发中广泛用于客户端与服务器之间的数据传输。在本章节中,我们将深入学习 JavaScript 中 JSON 的使用方法和最佳实践。
什么是 JSON
JSON(JavaScript Object Notation)是一种基于文本的数据交换格式,它基于 JavaScript 对象字面量语法,但独立于 JavaScript 语言。JSON 具有以下特点:
- 轻量级:相比 XML 等格式更加简洁
- 易读性:人类可读的文本格式
- 广泛支持:几乎所有编程语言都有 JSON 解析库
- 结构化:支持复杂的数据结构
javascript
// JSON 对象示例
const jsonString = `{
"name": "张三",
"age": 25,
"isStudent": true,
"hobbies": ["读书", "游泳", "编程"],
"address": {
"city": "北京",
"street": "长安街100号"
}
}`;
console.log(typeof jsonString); // "string"JSON 语法规则
基本语法
JSON 遵循严格的语法规则:
javascript
// 正确的 JSON 格式
const validJson = `{
"name": "张三",
"age": 25,
"isActive": true,
"salary": null,
"hobbies": ["读书", "游泳"],
"address": {
"city": "北京",
"zipcode": "100000"
}
}`;
// 错误的 JSON 格式(JavaScript 对象字面量)
const invalidJson = `{
name: "张三", // 键必须用双引号
'age': 25, // 键必须用双引号,不能用单引号
isActive: true, // 键必须用双引号
undefinedValue: undefined, // undefined 不是有效的 JSON 值
functionValue: function() {} // 函数不是有效的 JSON 值
}`;JSON 数据类型
JSON 支持以下数据类型:
javascript
// 字符串
const jsonString = `"Hello World"`;
// 数字
const jsonNumber = `42`;
const jsonFloat = `3.14159`;
// 布尔值
const jsonBoolean = `true`;
// null
const jsonNull = `null`;
// 对象
const jsonObject = `{
"name": "张三",
"age": 25
}`;
// 数组
const jsonArray = `[
"苹果",
"香蕉",
"橙子"
]`;
// 嵌套结构
const complexJson = `{
"users": [
{
"id": 1,
"name": "张三",
"profile": {
"age": 25,
"city": "北京"
}
},
{
"id": 2,
"name": "李四",
"profile": {
"age": 30,
"city": "上海"
}
}
],
"total": 2
}`;JSON 对象方法
JSON.parse() - 解析 JSON 字符串
javascript
// 基本解析
const jsonString = `{
"name": "张三",
"age": 25,
"isStudent": true
}`;
const obj = JSON.parse(jsonString);
console.log(obj.name); // "张三"
console.log(obj.age); // 25
console.log(obj.isStudent); // true
// 解析数组
const jsonArray = `["苹果", "香蕉", "橙子"]`;
const fruits = JSON.parse(jsonArray);
console.log(fruits[0]); // "苹果"
// 解析简单值
const jsonNumber = `42`;
const number = JSON.parse(jsonNumber);
console.log(number); // 42
// 带 reviver 参数的解析
const userData = `{
"name": "张三",
"birthDate": "1990-01-01",
"salary": "5000"
}`;
const parsedUser = JSON.parse(userData, (key, value) => {
if (key === "birthDate") {
return new Date(value);
}
if (key === "salary") {
return Number(value);
}
return value;
});
console.log(parsedUser.birthDate instanceof Date); // true
console.log(typeof parsedUser.salary); // "number"JSON.stringify() - 序列化为 JSON 字符串
javascript
// 基本序列化
const obj = {
name: "张三",
age: 25,
isStudent: true
};
const jsonString = JSON.stringify(obj);
console.log(jsonString);
// {"name":"张三","age":25,"isStudent":true}
// 序列化数组
const fruits = ["苹果", "香蕉", "橙子"];
const jsonArray = JSON.stringify(fruits);
console.log(jsonArray); // ["苹果","香蕉","橙子"]
// 带 replacer 参数的序列化
const user = {
name: "张三",
age: 25,
password: "secret123",
email: "zhangsan@example.com"
};
// 只序列化指定属性
const publicData = JSON.stringify(user, ["name", "age", "email"]);
console.log(publicData); // {"name":"张三","age":25,"email":"zhangsan@example.com"}
// 使用函数 replacer 过滤属性
const filteredData = JSON.stringify(user, (key, value) => {
// 排除密码字段
if (key === "password") {
return undefined;
}
return value;
});
console.log(filteredData); // {"name":"张三","age":25,"email":"zhangsan@example.com"}
// 格式化输出
const formattedJson = JSON.stringify(obj, null, 2);
console.log(formattedJson);
/*
{
"name": "张三",
"age": 25,
"isStudent": true
}
*/
// 使用制表符格式化
const tabFormatted = JSON.stringify(obj, null, "\t");
console.log(tabFormatted);toJSON() 方法
对象可以定义 toJSON() 方法来自定义序列化行为:
javascript
class User {
constructor(name, birthDate) {
this.name = name;
this.birthDate = birthDate;
}
// 自定义序列化
toJSON() {
return {
name: this.name,
age: this.getAge(),
birthDate: this.birthDate.toISOString().split("T")[0]
};
}
getAge() {
const today = new Date();
const birth = new Date(this.birthDate);
let age = today.getFullYear() - birth.getFullYear();
const monthDiff = today.getMonth() - birth.getMonth();
if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birth.getDate())) {
age--;
}
return age;
}
}
const user = new User("张三", new Date("1990-01-01"));
const json = JSON.stringify(user);
console.log(json);
// {"name":"张三","age":34,"birthDate":"1990-01-01"}JSON 的限制和注意事项
不支持的数据类型
javascript
// 以下类型在 JSON 中不被支持
const obj = {
func: function() { return "hello"; }, // 函数
undef: undefined, // undefined
sym: Symbol("id"), // Symbol
date: new Date(), // Date 对象
regex: /abc/g // 正则表达式
};
const json = JSON.stringify(obj);
console.log(json); // {"date":"2024-01-01T00:00:00.000Z"}
// 函数、undefined、Symbol 被忽略,Date 被转换为字符串
// 使用 toJSON() 处理特殊类型
class CustomObject {
constructor() {
this.date = new Date();
this.regex = /abc/g;
}
toJSON() {
return {
date: this.date.toISOString(),
regex: this.regex.toString()
};
}
}
const customObj = new CustomObject();
const customJson = JSON.stringify(customObj);
console.log(customJson);
// {"date":"2024-01-01T00:00:00.000Z","regex":"/abc/g"}循环引用问题
javascript
// 循环引用会导致错误
const obj = { name: "张三" };
obj.self = obj; // 创建循环引用
try {
const json = JSON.stringify(obj);
} catch (error) {
console.log("序列化错误:" + error.message);
// "Converting circular structure to JSON"
}
// 解决循环引用问题
function stringifyWithCircular(obj) {
const seen = new WeakSet();
return JSON.stringify(obj, (key, value) => {
if (typeof value === "object" && value !== null) {
if (seen.has(value)) {
return "[Circular]";
}
seen.add(value);
}
return value;
});
}
const jsonWithCircular = stringifyWithCircular(obj);
console.log(jsonWithCircular); // {"name":"张三","self":"[Circular]"}JSON 与 JavaScript 对象的转换
深拷贝对象
javascript
// 使用 JSON 进行深拷贝(有限制)
const original = {
name: "张三",
age: 25,
hobbies: ["读书", "游泳"],
address: {
city: "北京",
street: "长安街"
}
};
const copy = JSON.parse(JSON.stringify(original));
copy.name = "李四";
copy.hobbies.push("编程");
console.log(original.name); // "张三"(未改变)
console.log(original.hobbies); // ["读书", "游泳"](未改变)
console.log(copy.name); // "李四"
console.log(copy.hobbies); // ["读书", "游泳", "编程"]
// 注意:JSON 深拷贝的限制
const objWithFunc = {
name: "张三",
greet: function() { return "Hello"; },
date: new Date()
};
const jsonCopy = JSON.parse(JSON.stringify(objWithFunc));
console.log(jsonCopy.greet); // undefined(函数丢失)
console.log(jsonCopy.date instanceof Date); // false(变成字符串)数据验证和清理
javascript
// 验证 JSON 字符串
function isValidJson(str) {
try {
JSON.parse(str);
return true;
} catch (error) {
return false;
}
}
console.log(isValidJson('{"name":"张三"}')); // true
console.log(isValidJson('{"name":}')); // false
// 清理对象数据
function cleanObject(obj) {
return JSON.parse(JSON.stringify(obj, (key, value) => {
// 移除 undefined 和函数
if (value === undefined || typeof value === "function") {
return undefined;
}
// 转换日期对象
if (value instanceof Date) {
return value.toISOString();
}
return value;
}));
}
const dirtyObj = {
name: "张三",
age: undefined,
greet: function() { return "Hello"; },
date: new Date(),
valid: "有效数据"
};
const cleanObj = cleanObject(dirtyObj);
console.log(cleanObj);
// { name: "张三", date: "2024-01-01T00:00:00.000Z", valid: "有效数据" }JSON 在 Web 开发中的应用
AJAX 数据传输
javascript
// 发送 JSON 数据
async function sendUserData(userData) {
try {
const response = await fetch("/api/users", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(userData)
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
const result = await response.json();
console.log("用户创建成功:", result);
return result;
} catch (error) {
console.error("发送用户数据失败:", error);
throw error;
}
}
// 接收 JSON 数据
async function fetchUsers() {
try {
const response = await fetch("/api/users");
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
const users = await response.json();
console.log("获取到用户列表:", users);
return users;
} catch (error) {
console.error("获取用户列表失败:", error);
throw error;
}
}
// 使用示例
const newUser = {
name: "张三",
email: "zhangsan@example.com",
age: 25
};
// sendUserData(newUser);
// fetchUsers();本地存储
javascript
// 使用 localStorage 存储复杂对象
class StorageManager {
static save(key, data) {
try {
const jsonString = JSON.stringify(data);
localStorage.setItem(key, jsonString);
return true;
} catch (error) {
console.error("存储数据失败:", error);
return false;
}
}
static load(key) {
try {
const jsonString = localStorage.getItem(key);
if (jsonString === null) {
return null;
}
return JSON.parse(jsonString);
} catch (error) {
console.error("读取数据失败:", error);
return null;
}
}
static remove(key) {
localStorage.removeItem(key);
}
}
// 使用示例
const userPreferences = {
theme: "dark",
language: "zh-CN",
notifications: true
};
StorageManager.save("userPreferences", userPreferences);
const loadedPreferences = StorageManager.load("userPreferences");
console.log(loadedPreferences); // { theme: "dark", language: "zh-CN", notifications: true }配置文件处理
javascript
// 应用配置管理
class ConfigManager {
constructor() {
this.config = this.loadDefaultConfig();
this.loadStoredConfig();
}
loadDefaultConfig() {
return {
apiUrl: "https://api.example.com",
timeout: 5000,
retries: 3,
debug: false,
features: {
analytics: true,
notifications: false,
darkMode: true
}
};
}
loadStoredConfig() {
const storedConfig = localStorage.getItem("appConfig");
if (storedConfig) {
try {
const parsedConfig = JSON.parse(storedConfig);
this.config = { ...this.config, ...parsedConfig };
} catch (error) {
console.error("加载配置失败:", error);
}
}
}
getConfig(key = null) {
if (key) {
return this.config[key];
}
return this.config;
}
setConfig(key, value) {
this.config[key] = value;
this.saveConfig();
}
saveConfig() {
try {
localStorage.setItem("appConfig", JSON.stringify(this.config));
} catch (error) {
console.error("保存配置失败:", error);
}
}
resetConfig() {
this.config = this.loadDefaultConfig();
localStorage.removeItem("appConfig");
}
}
// 使用示例
const config = new ConfigManager();
console.log(config.getConfig("apiUrl")); // "https://api.example.com"
config.setConfig("debug", true);
console.log(config.getConfig("debug")); // trueJSON 最佳实践
1. 错误处理
javascript
// 安全的 JSON 解析
function safeJsonParse(str, defaultValue = null) {
try {
return JSON.parse(str);
} catch (error) {
console.warn("JSON 解析失败:", error.message);
return defaultValue;
}
}
// 安全的 JSON 序列化
function safeJsonStringify(obj, defaultValue = "{}") {
try {
return JSON.stringify(obj);
} catch (error) {
console.warn("JSON 序列化失败:", error.message);
return defaultValue;
}
}
// 使用示例
const invalidJson = '{"name":"张三",}'; // 无效的 JSON
const parsed = safeJsonParse(invalidJson, {});
console.log(parsed); // {}
const circularObj = { name: "张三" };
circularObj.self = circularObj;
const stringified = safeJsonStringify(circularObj, "{}");
console.log(stringified); // "{}"2. 性能优化
javascript
// 大数据量处理
class JsonProcessor {
// 流式处理大 JSON 数据
static processLargeJson(jsonString, chunkSize = 1000) {
try {
const data = JSON.parse(jsonString);
if (Array.isArray(data)) {
// 分块处理数组
const results = [];
for (let i = 0; i < data.length; i += chunkSize) {
const chunk = data.slice(i, i + chunkSize);
const processedChunk = this.processChunk(chunk);
results.push(...processedChunk);
}
return results;
}
return this.processObject(data);
} catch (error) {
console.error("处理 JSON 数据失败:", error);
return [];
}
}
static processChunk(chunk) {
return chunk.map(item => ({
...item,
processed: true,
processedAt: new Date().toISOString()
}));
}
static processObject(obj) {
return {
...obj,
processed: true,
processedAt: new Date().toISOString()
};
}
// 压缩 JSON 数据
static compressJson(obj, options = {}) {
const { removeNulls = false, removeEmptyStrings = false } = options;
return JSON.stringify(obj, (key, value) => {
if (removeNulls && value === null) {
return undefined;
}
if (removeEmptyStrings && value === "") {
return undefined;
}
return value;
});
}
}
// 使用示例
const largeData = JSON.stringify(
Array.from({ length: 5000 }, (_, i) => ({
id: i,
name: `用户${i}`,
email: `user${i}@example.com`
}))
);
console.time("处理大数据");
const processedData = JsonProcessor.processLargeJson(largeData, 1000);
console.timeEnd("处理大数据");
console.log("处理完成,数据量:", processedData.length);3. 数据验证
javascript
// JSON Schema 验证(简化版)
class JsonValidator {
static validate(data, schema) {
const errors = [];
for (const [key, rules] of Object.entries(schema)) {
const value = data[key];
// 必填验证
if (rules.required && (value === undefined || value === null)) {
errors.push(`字段 "${key}" 是必需的`);
continue;
}
if (value !== undefined) {
// 类型验证
if (rules.type && typeof value !== rules.type) {
errors.push(`字段 "${key}" 类型应该是 ${rules.type},实际是 ${typeof value}`);
}
// 字符串验证
if (typeof value === "string") {
if (rules.minLength && value.length < rules.minLength) {
errors.push(`字段 "${key}" 长度至少为 ${rules.minLength}`);
}
if (rules.maxLength && value.length > rules.maxLength) {
errors.push(`字段 "${key}" 长度最多为 ${rules.maxLength}`);
}
if (rules.pattern && !new RegExp(rules.pattern).test(value)) {
errors.push(`字段 "${key}" 格式不正确`);
}
}
// 数字验证
if (typeof value === "number") {
if (rules.min !== undefined && value < rules.min) {
errors.push(`字段 "${key}" 最小值为 ${rules.min}`);
}
if (rules.max !== undefined && value > rules.max) {
errors.push(`字段 "${key}" 最大值为 ${rules.max}`);
}
}
// 数组验证
if (Array.isArray(value)) {
if (rules.minItems !== undefined && value.length < rules.minItems) {
errors.push(`字段 "${key}" 至少包含 ${rules.minItems} 个项目`);
}
if (rules.maxItems !== undefined && value.length > rules.maxItems) {
errors.push(`字段 "${key}" 最多包含 ${rules.maxItems} 个项目`);
}
}
}
}
return {
valid: errors.length === 0,
errors: errors
};
}
}
// 使用示例
const userData = {
name: "张三",
age: 25,
email: "zhangsan@example.com",
hobbies: ["读书", "游泳"]
};
const userSchema = {
name: { required: true, type: "string", minLength: 2, maxLength: 50 },
age: { required: true, type: "number", min: 0, max: 150 },
email: { required: true, type: "string", pattern: "^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$" },
hobbies: { type: "object", minItems: 1, maxItems: 10 }
};
const validation = JsonValidator.validate(userData, userSchema);
console.log("验证结果:", validation);实际应用示例
1. API 数据处理工具
javascript
class ApiDataProcessor {
// 标准化 API 响应
static normalizeResponse(data) {
return {
success: true,
data: data,
timestamp: new Date().toISOString(),
version: "1.0"
};
}
// 标准化错误响应
static normalizeError(error, code = "UNKNOWN_ERROR") {
return {
success: false,
error: {
code: code,
message: error.message || "未知错误",
details: error.details || null
},
timestamp: new Date().toISOString(),
version: "1.0"
};
}
// 转换数据格式
static transformData(data, mapping) {
if (!data) return data;
if (Array.isArray(data)) {
return data.map(item => this.transformItem(item, mapping));
}
return this.transformItem(data, mapping);
}
static transformItem(item, mapping) {
const transformed = {};
for (const [newKey, oldKey] of Object.entries(mapping)) {
if (typeof oldKey === "string") {
transformed[newKey] = this.getNestedValue(item, oldKey);
} else if (typeof oldKey === "function") {
transformed[newKey] = oldKey(item);
}
}
return transformed;
}
static getNestedValue(obj, path) {
return path.split(".").reduce((current, key) => {
return current && current[key] !== undefined ? current[key] : null;
}, obj);
}
// 缓存处理
static createCacheKey(endpoint, params = {}) {
const sortedParams = Object.keys(params)
.sort()
.map(key => `${key}=${params[key]}`)
.join("&");
return `${endpoint}?${sortedParams}`;
}
static cacheResponse(key, data, ttl = 300000) { // 5分钟默认过期
const cacheData = {
data: data,
timestamp: Date.now(),
expiresAt: Date.now() + ttl
};
try {
localStorage.setItem(`api_cache_${key}`, JSON.stringify(cacheData));
} catch (error) {
console.warn("缓存数据失败:", error);
}
}
static getCachedResponse(key) {
try {
const cached = localStorage.getItem(`api_cache_${key}`);
if (!cached) return null;
const cacheData = JSON.parse(cached);
if (cacheData.expiresAt < Date.now()) {
localStorage.removeItem(`api_cache_${key}`);
return null;
}
return cacheData.data;
} catch (error) {
console.warn("读取缓存失败:", error);
return null;
}
}
}
// 使用示例
const apiResponse = {
users: [
{
id: 1,
personal_info: {
first_name: "张",
last_name: "三",
contact: {
email_address: "zhangsan@example.com"
}
},
account_status: "active"
}
]
};
const mapping = {
id: "id",
firstName: "personal_info.first_name",
lastName: "personal_info.last_name",
email: "personal_info.contact.email_address",
status: "account_status",
fullName: (item) => `${item.personal_info.first_name}${item.personal_info.last_name}`
};
const transformed = ApiDataProcessor.transformData(apiResponse.users, mapping);
console.log("转换后的数据:", transformed);2. 配置文件管理器
javascript
class ConfigFileManager {
constructor(configPath = "config.json") {
this.configPath = configPath;
this.config = this.loadConfig();
}
loadConfig() {
// 在浏览器环境中使用 localStorage
if (typeof window !== "undefined") {
const stored = localStorage.getItem(this.configPath);
if (stored) {
try {
return JSON.parse(stored);
} catch (error) {
console.error("解析配置文件失败:", error);
}
}
}
// 返回默认配置
return this.getDefaultConfig();
}
getDefaultConfig() {
return {
app: {
name: "My Application",
version: "1.0.0",
debug: false
},
api: {
baseUrl: "https://api.example.com",
timeout: 5000,
retries: 3
},
ui: {
theme: "light",
language: "zh-CN",
pageSize: 20
},
features: {
analytics: true,
notifications: true,
darkMode: false
}
};
}
get(path) {
return path.split(".").reduce((current, key) => {
return current && current[key] !== undefined ? current[key] : undefined;
}, this.config);
}
set(path, value) {
const keys = path.split(".");
const lastKey = keys.pop();
const target = keys.reduce((current, key) => {
if (current[key] === undefined) {
current[key] = {};
}
return current[key];
}, this.config);
target[lastKey] = value;
this.saveConfig();
}
saveConfig() {
try {
const jsonString = JSON.stringify(this.config, null, 2);
// 在浏览器环境中保存到 localStorage
if (typeof window !== "undefined") {
localStorage.setItem(this.configPath, jsonString);
}
// 在 Node.js 环境中保存到文件
if (typeof require !== "undefined") {
const fs = require("fs");
fs.writeFileSync(this.configPath, jsonString, "utf8");
}
} catch (error) {
console.error("保存配置文件失败:", error);
}
}
validateConfig() {
const requiredFields = [
"app.name",
"app.version",
"api.baseUrl"
];
const missingFields = requiredFields.filter(field =>
this.get(field) === undefined
);
if (missingFields.length > 0) {
throw new Error(`缺少必需的配置字段:${missingFields.join(", ")}`);
}
return true;
}
exportConfig() {
return JSON.stringify(this.config, null, 2);
}
importConfig(configString) {
try {
const newConfig = JSON.parse(configString);
this.config = { ...this.config, ...newConfig };
this.saveConfig();
return true;
} catch (error) {
console.error("导入配置失败:", error);
return false;
}
}
resetConfig() {
this.config = this.getDefaultConfig();
this.saveConfig();
}
}
// 使用示例
const configManager = new ConfigFileManager();
// 获取配置
console.log(configManager.get("app.name")); // "My Application"
console.log(configManager.get("api.timeout")); // 5000
// 设置配置
configManager.set("app.debug", true);
configManager.set("ui.theme", "dark");
// 验证配置
try {
configManager.validateConfig();
console.log("配置验证通过");
} catch (error) {
console.error("配置验证失败:", error.message);
}
// 导出配置
const configExport = configManager.exportConfig();
console.log("导出的配置:", configExport);
// 重置配置
// configManager.resetConfig();总结
JavaScript JSON 的核心要点:
- 基本概念:轻量级数据交换格式,基于 JavaScript 对象语法
- 语法规则:严格的键值对格式,键必须用双引号
- 核心方法:JSON.parse() 解析,JSON.stringify() 序列化
- 数据类型:支持字符串、数字、布尔值、null、对象、数组
- 限制注意:不支持函数、undefined、Symbol、循环引用
- 自定义处理:toJSON() 方法、replacer 和 reviver 参数
- 实际应用:AJAX 数据传输、本地存储、配置文件处理
- 最佳实践:错误处理、性能优化、数据验证
- 工具应用:API 数据处理、配置文件管理
掌握 JSON 处理是 Web 开发的基础技能。在下一章节中,我们将学习 JavaScript 的异步编程。