JavaScript 中JSON 數據遍歷
1. JSON 字符串轉對象後遍歷
1.1 解析 JSON 字符串
const jsonString = '{"users": [{"id": 1, "name": "張三"}, {"id": 2, "name": "李四"}]}';
const data = JSON.parse(jsonString);
// 遍歷數組
data.users.forEach(user => {
console.log(`ID: ${user.id}, 姓名: ${user.name}`);
});
// 1.2 從 API 獲取的 JSON
fetch('/api/user/realname/王')
.then(response => response.json())
.then(data => {
// 遍歷返回的 JSON 數據
if (Array.isArray(data)) {
data.forEach(user => {
console.log(user.realname, user.email);
});
}
});
2. 遍歷 JSON 對象(Object)
const user = {
"id": 1,
"username": "zhangsan",
"realname": "張三",
"email": "zhangsan@example.com",
"department": {
"id": 101,
"name": "技術部"
}
};
// 2.1 Object.keys() + forEach
Object.keys(user).forEach(key => {
console.log(`${key}: ${user[key]}`);
});
// 2.2 for...in 循環(會遍歷原型鏈屬性)
for (const key in user) {
if (user.hasOwnProperty(key)) {
console.log(`${key}: ${user[key]}`);
}
}
// 2.3 Object.entries() - 獲取鍵值對數組
Object.entries(user).forEach(([key, value]) => {
console.log(`${key}: ${JSON.stringify(value)}`);
});
// 2.4 Object.values() - 只獲取值
Object.values(user).forEach(value => {
console.log(value);
});
3. 遍歷嵌套的 JSON 數據
const company = {
"companyName": "ABC公司",
"departments": [
{
"id": 1,
"name": "技術部",
"employees": [
{"id": 101, "name": "張三", "role": "前端開發"},
{"id": 102, "name": "李四", "role": "後端開發"}
]
},
{
"id": 2,
"name": "市場部",
"employees": [
{"id": 201, "name": "王五", "role": "市場專員"},
{"id": 202, "name": "李莉", "role": "價格管理"},
{"id": 203, "name": "張琪", "role": "檔案管理"},
{"id": 204, "name": "郝錚", "role": "綜合管理"}
]
}
]
};
// 3.1 多層嵌套遍歷
company.departments.forEach(dept => {
console.log(`部門: ${dept.name}`);
dept.employees.forEach(emp => {
console.log(` - ${emp.name} (${emp.role})`);
});
});
// 3.2 遞歸遍歷所有屬性
function traverseJSON(obj, depth = 0) {
const indent = ' '.repeat(depth);
if (Array.isArray(obj)) {
obj.forEach(item => traverseJSON(item, depth + 1));
} else if (obj !== null && typeof obj === 'object') {
Object.entries(obj).forEach(([key, value]) => {
if (typeof value === 'object') {
console.log(`${indent}${key}:`);
traverseJSON(value, depth + 1);
} else {
console.log(`${indent}${key}: ${value}`);
}
});
} else {
console.log(`${indent}${obj}`);
}
}
traverseJSON(company);
4. 處理從 API 返回的 JSON 數據
// 假設 API 返回:{ "success": true, "data": [{...}, {...}], "total": 2 }
async function fetchAndProcessUsers() {
try {
const response = await fetch('/api/users');
const result = await response.json();
// 4.1 檢查 API 返回狀態
if (!result.success) {
throw new Error(result.message || '請求失敗');
}
// 4.2 遍歷數據
const users = result.data;
// 方式1: 簡單遍歷
users.forEach((user, index) => {
console.log(`用户${index + 1}:`, user);
});
// 方式2: 使用 map 轉換數據
const userNames = users.map(user => ({
id: user.id,
displayName: `${user.realname} (${user.username})`,
department: user.deptname
}));
// 方式3: 使用 filter 篩選
const activeUsers = users.filter(user =>
user.status === 'active' && user.deptname === '技術部'
);
// 方式4: 使用 reduce 統計
const departmentCount = users.reduce((acc, user) => {
acc[user.deptname] = (acc[user.deptname] || 0) + 1;
return acc;
}, {});
console.log('部門統計:', departmentCount);
return userNames;
} catch (error) {
console.error('處理數據失敗:', error);
}
}
5. 將遍歷結果轉為 HTML
async function displayUsersInTable() {
const response = await fetch('/api/user/realname/王');
const users = await response.json();
const tableBody = document.querySelector('#userTable tbody');
tableBody.innerHTML = ''; // 清空現有內容
// 遍歷 JSON 數據生成表格行
users.forEach(user => {
const row = document.createElement('tr');
// 創建單元格
const cells = [
user.id,
user.realname,
user.username,
user.deptname,
user.mobile,
user.email
];
cells.forEach(cellData => {
const cell = document.createElement('td');
cell.textContent = cellData || 'N/A';
row.appendChild(cell);
});
// 添加操作按鈕
const actionCell = document.createElement('td');
actionCell.innerHTML = `
<button onclick="editUser(${user.id})">編輯</button>
<button onclick="deleteUser(${user.id})">刪除</button>
`;
row.appendChild(actionCell);
tableBody.appendChild(row);
});
}
使用模板字符串
function displayUsersWithTemplate(users) {
const container = document.getElementById('userContainer');
const userCards = users.map(user => `
<div class="user-card">
<h3>${escapeHtml(user.realname)}</h3>
<p><strong>用户名:</strong> ${escapeHtml(user.username)}</p>
<p><strong>部門:</strong> ${escapeHtml(user.deptname || '未分配')}</p>
<p><strong>手機:</strong> ${escapeHtml(user.mobile || 'N/A')}</p>
<p><strong>郵箱:</strong> ${escapeHtml(user.email || 'N/A')}</p>
<button class="btn-view" data-id="${user.id}">查看詳情</button>
</div>
`).join('');
container.innerHTML = userCards;
// 添加事件監聽
container.querySelectorAll('.btn-view').forEach(button => {
button.addEventListener('click', (e) => {
const userId = e.target.dataset.id;
viewUserDetail(userId);
});
});
}
防止 XSS 攻擊的簡單轉義函數
function escapeHtml(text) {
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
6. 使用現代 JavaScript 特性
6.1 使用可選鏈和空值合併
users?.forEach(user => {
const email = user.email ?? '暫無郵箱';
const dept = user.department?.name ?? '未分配部門';
console.log(`${user.realname} - ${dept} - ${email}`);
});
6.2 使用解構賦值
users.forEach(({ id, realname: name, email = '無郵箱' }) => {
console.log(`ID: ${id}, 姓名: ${name}, 郵箱: ${email}`);
});
6.3 使用 flatMap 處理嵌套數組
const allEmployees = companyData.departments.flatMap(dept =>
dept.employees.map(emp => ({
...emp,
department: dept.name
}))
);
6.4 使用 Set 去重
const uniqueDepartments = [...new Set(users.map(user => user.deptname))];
7. 處理大型 JSON 數據的技巧
7.1 分塊處理(避免阻塞主線程)
async function processLargeDataset(users) {
const chunkSize = 100;
for (let i = 0; i < users.length; i += chunkSize) {
const chunk = users.slice(i, i + chunkSize);
// 處理當前塊
chunk.forEach(user => {
// 處理邏輯
});
// 讓出主線程,避免阻塞
await new Promise(resolve => setTimeout(resolve, 0));
}
}
7.2 使用 Web Worker 處理大型 JSON
const worker = new Worker('json-processor.js');
worker.postMessage({ users: largeJsonData });
worker.onmessage = (e) => {
console.log('處理結果:', e.data);
};
// json-processor.js
self.onmessage = (e) => {
const users = e.data.users;
const processed = users.map(user => {
// 在 Worker 線程中處理
return { ...user, processed: true };
});
self.postMessage(processed);
};
8. 錯誤處理和驗證
async function safeJsonTraversal(url) {
try {
const response = await fetch(url);
// 驗證響應
if (!response.ok) {
throw new Error(`HTTP錯誤: ${response.status}`);
}
// 解析 JSON
const data = await response.json();
// 驗證數據結構
if (!data || typeof data !== 'object') {
throw new Error('無效的JSON格式');
}
// 安全遍歷
if (Array.isArray(data)) {
return data.map(item => ({
...item,
// 確保必要字段存在
id: item.id || 0,
realname: item.realname || '未知用户'
}));
}
return data;
} catch (error) {
console.error('JSON處理失敗:', error);
return null;
}
}
總結
|
場景
|
推薦方法
|
示例
|
|
遍歷數組
|
forEach(), for...of
|
users.forEach(user => {...})
|
|
轉換數組
|
map()
|
users.map(u => u.name)
|
|
篩選數組
|
filter()
|
users.filter(u => u.active)
|
|
遍歷對象
|
Object.entries()
|
Object.entries(obj)
|
|
獲取鍵
|
Object.keys()
|
Object.keys(obj)
|
|
獲取值
|
Object.values()
|
Object.values(obj)
|
關鍵點:
- 先確定 JSON 數據的結構(數組還是對象)
- 使用合適的遍歷方法
- 注意錯誤處理和空值檢查
- 對於複雜嵌套,考慮使用遞歸
- 處理用户輸入時注意安全(防 XSS)