JSON 核心優勢
- 輕量級、純文字格式、跨語言通用
- 原生支援物件/陣列巢狀結構
- JavaScript 原生解析,無需額外庫
- PHP 5.2+ 內建
json_encode/json_decode
PHP → JavaScript 資料流向
後端編碼 (json.php)
<?php
header('Content-Type: application/json; charset=utf-8');
$data = [
'name' => '希亞',
'nick' => 'Gonn',
'contact' => [
'email' => 'gonnsai@163.com',
'website' => 'https://www.example.com',
],
'tags' => ['PHP', 'JSON', 'API'],
'active' => true,
'score' => 98.5
];
// JSONP 回調支援 (跨域舊方案)
$callback = $_GET['callback'] ?? 'callback';
$json = json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
echo "$callback($json)";
?>
前端解析
<script>
function callback(response) {
// response 直接是 JavaScript 物件
document.getElementById('name').textContent = response.name;
document.getElementById('nick').textContent = response.nick;
document.getElementById('email').textContent = response.contact.email;
document.getElementById('website').textContent = response.contact.website;
// 陣列遍歷
response.tags.forEach(tag => {
const el = document.createElement('span');
el.className = 'tag';
el.textContent = tag;
document.getElementById('tags').appendChild(el);
});
}
</script>
<!-- JSONP 載入 -->
<script src="json.php?callback=callback"></script>
<div>姓名: <span id="name"></span></div>
<div>暱稱: <span id="nick"></span></div>
<div>Email: <span id="email"></span></div>
<div>網站: <span id="website"></span></div>
<div>標籤: <span id="tags"></span></div>
JavaScript → PHP 資料流向
前端編碼 (需 json2.js 或現代瀏覽器原生 JSON)
<form id="userForm" action="save.php" method="POST">
<input type="hidden" name="json_data" id="jsonData">
<input type="text" id="txtName" placeholder="姓名">
<input type="email" id="txtEmail" placeholder="Email">
<input type="password" id="txtPwd" placeholder="密碼">
<button type="submit">提交</button>
</form>
<script>
// 現代瀏覽器原生支援 JSON.stringify
document.getElementById('userForm').addEventListener('submit', function(e) {
e.preventDefault();
const userData = {
name: document.getElementById('txtName').value,
email: document.getElementById('txtEmail').value,
password: document.getElementById('txtPwd').value
};
// 物件序列化為 JSON 字串
document.getElementById('jsonData').value = JSON.stringify(userData);
// 顯示確認
console.log('將提交:', document.getElementById('jsonData').value);
this.submit();
});
</script>
後端解碼 (save.php)
<?php
header('Content-Type: text/html; charset=utf-8');
$jsonString = $_POST['json_data'] ?? '';
// 處理 magic_quotes_gpc (PHP 5.4-)
if (get_magic_quotes_gpc()) {
$jsonString = stripslashes($jsonString);
}
// 解碼為 PHP 物件 (stdClass)
$user = json_decode($jsonString);
// 或解碼為關聯陣列 (true)
$userArr = json_decode($jsonString, true);
var_dump($user);
echo "<br><br>";
echo "姓名: {$user->name}<br>";
echo "Email: {$user->email}<br>";
echo "密碼: {$user->password}<br>";
?>
進階編碼選項 (PHP 5.4+)
| 常數 | 作用 |
| JSON_UNESCAPED_UNICODE | 不轉義 Unicode (中文可讀),預設轉 \uXXXX |
| JSON_UNESCAPED_SLASHES | 不轉義 / (URL 更乾淨) |
| JSON_NUMERIC_CHECK | 數字字串轉數字型別 |
| JSON_PRETTY_PRINT | 格式化輸出 (除錯用) |
| JSON_PRESERVE_ZERO_FRACTION | 保留浮點數 .0 (如 1.0 不變 1) |
| JSON_FORCE_OBJECT | 空陣列輸出 {} 而非 [] |
// 推薦生產環境組合
$flags = JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_NUMERIC_CHECK;
echo json_encode($data, $flags);
錯誤處理與除錯
<?php
$json = '{"name": "test", "age": 25}';
$user = json_decode($json);
if (json_last_error() !== JSON_ERROR_NONE) {
throw new Exception('JSON 解析失敗: ' . json_last_error_msg());
}
// 常見錯誤類型
// JSON_ERROR_DEPTH - 堆疊深度超限
// JSON_ERROR_STATE_MISMATCH - 狀態不匹配 (編碼問題)
// JSON_ERROR_CTRL_CHAR - 控制字元錯誤
// JSON_ERROR_SYNTAX - 語法錯誤 (最常見)
// JSON_ERROR_UTF8 - UTF-8 編碼錯誤
?>
現代替代方案:AJAX + Fetch API
// 現代前端標準寫法 (無需 JSONP、隱藏表單)
async function saveUser(userData) {
const response = await fetch('/api/user/save', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-Token': getCsrfToken()
},
body: JSON.stringify(userData)
});
if (!response.ok) throw new Error(`HTTP ${response.status}`);
return response.json();
}
// PHP 端接收 JSON 原始資料
$input = file_get_contents('php://input');
$data = json_decode($input, true);
安全最佳實踐
- ✅ 設定正確
Content-Type: application/json
- ✅ 輸入驗證:
json_decode 後檢查必要欄位、型別、長度
- ✅ 輸出編碼:HTML 上下文用
htmlspecialchars,JS 上下文用 json_encode
- ✅ CSRF 保護:AJAX 請求攜帶 Token
- ✅ 速率限制:防止 API 濫用
- ❌ 禁用
eval() 解析 JSON
- ❌ 信任客戶端資料 (永遠在後端驗證)