JSON (JavaScript Object Notation) 是現代 Web 應用的核心資料交換格式。PHP 5.2+ 內建 json_encode()、json_decode(),本文系統整理編碼選項、中文處理、JavaScript 交互、跨域技巧、錯誤排查等實戰知識。
// 編碼:PHP 變數 → JSON 字串 json_encode($value, $flags = 0, $depth = 512): string|false // 解碼:JSON 字串 → PHP 變數 json_decode($json, $assoc = false, $depth = 512, $options = 0): mixed
| 常數 | 說明 | 適用場景 |
|---|---|---|
| JSON_HEX_TAG | < > 轉 \u003C \u003E | 防止 XSS,嵌入 HTML script 標籤時 |
| JSON_HEX_APOS | ' 轉 \u0027 | JS 字串單引號包裹時 |
| JSON_HEX_QUOT | " 轉 \u0022 | HTML 屬性值中輸出 JSON |
| JSON_HEX_AMP | & 轉 \u0026 | URL 參數傳遞 JSON |
| JSON_UNESCAPED_UNICODE | 不轉義 Unicode (中文可讀) | **強烈建議預設開啟**,除非需相容舊系統 |
| JSON_UNESCAPED_SLASHES | / 不轉義 | URL、路徑較易讀 |
| JSON_NUMERIC_CHECK | 數值字串轉數字 | API 回傳數值型欄位,謹慎使用 |
| JSON_PRESERVE_ZERO_FRACTION | 保留 .0 (1.0 不變 1) | 需嚴格區分整數/浮點數 |
| JSON_PRETTY_PRINT | 美化縮排輸出 | 除錯、日誌、配置檔 |
| JSON_THROW_ON_ERROR | 錯誤拋出 Exception (PHP 7.3+) | 現代錯誤處理流程 |
$default_flags = JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP; $json = json_encode($data, $default_flags);
SET NAMES utf8mb4Content-Type: application/json; charset=utf-8iconv('GBK', 'UTF-8', $str) 轉碼後再 encode// PHP 關聯陣列 → JSON 物件
['id' => 1, 'name' => '張三'] → {"id":1,"name":"張三"}
// PHP 索引陣列 → JSON 陣列
['蘋果', '香蕉'] → ["蘋果","香蕉"]
// 物件屬性 → JSON 物件
class User { public $id=1; public $name='張三'; }
new User() → {"id":1,"name":"張三"}
// 多維混合
[['id'=>1], ['id'=>2]] → [{"id":1},{"id":2}]
// 現代瀏覽器 (IE10+)
const data = JSON.parse(jsonString);
// jQuery (自動處理 Content-Type)
$.getJSON('/api/users', function(data) { ... });
// Fetch API
fetch('/api/users')
.then(r => r.json())
.then(data => console.log(data));
// 避免使用 eval() - 極大安全風險
伺服端 callback.php:
<?php
header('Content-Type: application/javascript; charset=utf-8');
$data = ['name' => '張三', 'time' => time()];
$callback = $_GET['callback'] ?? 'callback';
// 安全驗證 callback 只含字母數字底線
if (!preg_match('/^[\w.]+$/', $callback)) exit('Invalid callback');
echo "$callback(" . json_encode($data, JSON_UNESCAPED_UNICODE) . ");";
客戶端:
<script>
function handleUser(data) { console.log(data.name); }
</script>
<script src="callback.php?callback=handleUser"></script>
<?php
// API 端統一加入
header('Access-Control-Allow-Origin: https://your-frontend.com'); // 或 * (非帶憑證)
header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type, Authorization');
header('Access-Control-Allow-Credentials: true');
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
http_response_code(204);
exit;
}
$json = json_encode($data, JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE);
// PHP 7.3+ 失敗拋出 JsonException
// 手動檢查 (舊版相容)
$json = json_encode($data);
if (json_last_error() !== JSON_ERROR_NONE) {
error_log('JSON 編碼失敗: ' . json_last_error_msg());
// 降級處理:移除問題資料、記錄、回傳錯誤格式
}
JSON_UNESCAPED_UNICODE 減少體積 (中文不轉義)igbinary、msgpack 二進位序列化替代 JSONgzip、brotli 壓縮 JSON 回應掌握 JSON 編解碼細節、跨域方案選型、錯誤處理模式,能讓前後端協作更順暢、API 更穩健高效。