json_encode 是 PHP 中將數組或對象轉換為 JSON 字符串的核心函數,廣泛用於 API 接口、前端圖表數據傳輸、配置存儲等場景。本文通過一個完整的「數據庫查詢 → JSON 編碼 → AJAX 獲取 → 圖表渲染」實例,詳細講解實用技巧與常見坑點。
<?php
// 現代寫法:使用 PDO 防止 SQL 注入
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8', 'user', 'pass');
$stmt = $pdo->prepare('SELECT event_date, data_value FROM statistics WHERE created_at BETWEEN ? AND ?');
$stmt->execute([$beginTime, $endTime]);
$xData = [];
$yData = [];
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$xData[] = $row['event_date']; // X 軸:日期標籤
$yData[] = (int)$row['data_value']; // Y 軸:數值(強制轉整型)
}
// 關鍵:構建前端圖表庫(如 ECharts、Chart.js)所需的結構
$result = [
'categories' => $xData, // 坐標軸標籤
'series' => [[
'name' => '訪問量',
'data' => $yData,
'type' => 'line'
]]
];
// 設置正確的 Content-Type,避免前端誤判
header('Content-Type: application/json; charset=utf-8');
echo json_encode($result, JSON_UNESCAPED_UNICODE | JSON_NUMERIC_CHECK);
<script src="https://cdn.jsdelivr.net/npm/echarts@5/dist/echarts.min.js"></script>
<div id="chart" style="width: 600px; height: 400px;"></div>
<script>
fetch('api/chart_data.php?begin=2024-01-01&end=2024-01-31')
.then(res => res.json())
.then(data => {
const chart = echarts.init(document.getElementById('chart'));
chart.setOption({
xAxis: { type: 'category', data: data.categories },
yAxis: { type: 'value' },
series: data.series
});
})
.catch(err => console.error('數據加載失敗:', err));
</script>
| 常量 | 作用 | 推薦場景 |
|---|---|---|
JSON_UNESCAPED_UNICODE | 不轉義中文等 Unicode 字符,輸出可讀性強 | 所有包含中文的輸出 必加 |
JSON_NUMERIC_CHECK | 將數字字符串轉為真正的數字類型 | 數據庫查出的數值字段,防止前端當字符串處理 |
JSON_UNESCAPED_SLASHES | 不轉義斜杠 / | 包含 URL、路徑時 |
JSON_PRETTY_PRINT | 格式化縮進,便於調試 | 開發調試、配置文件生成 |
JSON_PRESERVE_ZERO_FRACTION | 保留浮點數的 .0(如 1.0 不變為 1) | 需要嚴格數字格式的 API |
推薦組合:JSON_UNESCAPED_UNICODE | JSON_NUMERIC_CHECK
原因:未加 JSON_UNESCAPED_UNICODE。
解決:始終加上此選項,或升級 PHP 5.4+(默認支持)。
原因:數據庫驅動返回所有字段為字符串。
解決:使用 JSON_NUMERIC_CHECK 或在查詢時轉型 CAST(col AS UNSIGNED)、PHP 中 (int)$val。
原因:默認最大深度 512 層。
解決:遞歸數據結構扁平化,或設置 ini_set('json.encode.max_depth', 1024)(PHP 8.0+)。
現象:PDOStatement、文件句柄等資源類型編碼為 null。
解決:先 fetchAll() 獲取純數組再編碼。
class ApiResponse implements JsonSerializable {
private $data;
private $meta;
public function jsonSerialize(): mixed {
return [
'code' => 200,
'data' => $this->data,
'meta' => $this->meta
];
}
}
// 直接 echo json_encode($response) 即可自動調用 jsonSerialize()
function customJsonEncode($data) {
array_walk_recursive($data, function(&$value, $key) {
if (in_array($key, ['password', 'token', 'secret'])) {
$value = '******'; // 脫敏
}
});
return json_encode($data, JSON_UNESCAPED_UNICODE);
}
json_encode($arr, JSON_UNESCAPED_UNICODE | JSON_NUMERIC_CHECK) → 設置 Content-Type: application/jsonfetch + res.json(),避免 eval 風險{code, message, data}json_encode 不支持流式,需手動分塊)掌握 json_encode 的細節,能讓你的 API 更健壯、前端對接更順暢。希望本文能成為你開發中的實用參考。