核心函數速查
| 函數 | 用途 | 常用選項 |
json_encode() | PHP 值 → JSON 字串 | JSON_UNESCAPED_UNICODE、JSON_UNESCAPED_SLASHES、JSON_PRETTY_PRINT |
json_decode() | JSON 字串 → PHP 值 | assoc=true 回傳陣列、depth 限制深度、options (JSON_BIGINT_AS_STRING) |
json_last_error() | 取得最後錯誤碼 | 搭配 json_last_error_msg() |
基礎範例
<?php
$json = '{"a":1,"b":2,"c":3,"d":4,"e":5}';
// 解碼為物件 (stdClass)
$obj = json_decode($json);
var_dump($obj->a); // int(1)
// 解碼為關聯陣列
$arr = json_decode($json, true);
var_dump($arr['a']); // int(1)
// 陣列編碼為 JSON
$data = ['name' => 'John', 'age' => 30, 'tags' => ['php', 'json']];
echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
/*
{
"name": "John",
"age": 30,
"tags": ["php", "json"]
}
*/
?>
實戰場景:API 回應統一格式
<?php
function apiResponse(int $code, string $msg, $data = null, int $httpCode = 200): void {
http_response_code($httpCode);
header('Content-Type: application/json; charset=utf-8');
echo json_encode([
'code' => $code,
'msg' => $msg,
'data' => $data,
'timestamp' => time()
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
exit;
}
// 使用
apiResponse(0, '成功', ['user' => ['id' => 1, 'name' => 'Alice']]);
apiResponse(40001, '參數錯誤', null, 400);
?>
巢狀物件轉陣列:遞歸函數
<?php
/**
* 將 stdClass 物件樹遞歸轉為純陣列
*/
function objectToArray($obj): array {
if (is_object($obj)) $obj = (array)$obj;
if (!is_array($obj)) return $obj;
$arr = [];
foreach ($obj as $k => $v) {
$arr[$k] = objectToArray($v);
}
return $arr;
}
// 測試
$json = '{"user":{"id":1,"profile":{"name":"Bob","addr":{"city":"Taipei"}}}}';
$obj = json_decode($json);
$arr = objectToArray($obj);
/*
[
'user' => [
'id' => 1,
'profile' => [
'name' => 'Bob',
'addr' => ['city' => 'Taipei']
]
]
]
*/
?>
大整數精度問題(JSON_BIGINT_AS_STRING)
<?php
$json = '{"id": 1234567890123456789}';
// 預設會變成 float 丟失精度
var_dump(json_decode($json)); // float(1.2345678901235E+18)
// 保持字串
var_dump(json_decode($json, false, 512, JSON_BIGINT_AS_STRING)); // string(19) "1234567890123456789"
?>
錯誤處理最佳實踐
<?php
function safeJsonDecode(string $json, bool $assoc = true) {
$result = json_decode($json, $assoc);
if (json_last_error() !== JSON_ERROR_NONE) {
throw new RuntimeException('JSON 解析失敗: ' . json_last_error_msg());
}
return $result;
}
try {
$data = safeJsonDecode($input);
} catch (RuntimeException $e) {
logError($e->getMessage());
apiResponse(50000, '資料格式錯誤');
}
?>
效能優化建議
- 避免重複編碼/解碼:在服務層統一處理,控制器直接操作陣列/物件。
- 大量資料序列化考慮
igbinary、msgpack 二進制格式(需擴展)。
- API 輸出開啟
opcache.enable_cli=1 減少編譯開銷。
常見陷阱檢查表
| 現象 | 原因 | 修正 |
| 中文變 \uXXXX | 未加 JSON_UNESCAPED_UNICODE | json_encode($data, JSON_UNESCAPED_UNICODE) |
| 斜線被轉義 \/ | 預設行為 | 加 JSON_UNESCAPED_SLASHES |
| 空陣列變 {} | PHP 關聯陣列鍵非連續 | 用 array_values() 重建索引或接受物件形式 |
| stdClass 無法 foreach | 未轉陣列 | json_decode($json, true) 或 (array)$obj |
| 科學記號輸出 | 大整數超出 PHP_INT_MAX | JSON_BIGINT_AS_STRING |
掌握 json_encode/decode 選項與錯誤處理,讓 JSON 交互更安全、更高效、更符合規範。