**PHP 5.2.0+ 內置 json_encode() / json_decode() 是標準、高性能、安全的解決方案**。本文原示例的手寫遞歸函數 array_to_json 存在嚴重缺陷:**不支持 Unicode 轉義、浮點數精度丟失、無法處理資源/對象、JSON 格式不嚴格 (單引號、尾逗號風險)**。生產環境**嚴禁**使用手寫實現。
<?php
$data = [
'id' => 1001,
'name' => '張三',
'tags' => ['vip', 'active'],
'score' => 98.5,
'metadata' => (object)['source' => 'web', 'version' => 2],
'created_at' => new DateTime('2024-01-01'),
];
// 基礎輸出
echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
/* {"id":1001,"name":"張三","tags":["vip","active"],"score":98.5,"metadata":{"source":"web","version":2},"created_at":"2024-01-01 00:00:00"} */
// 美化輸出 (調試/日誌)
echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
/* {
"id": 1001,
"name": "張三",
"tags": ["vip", "active"],
"score": 98.5,
"metadata": {"source": "web", "version": 2},
"created_at": "2024-01-01 00:00:00"
} */
?>
| 常量 | 作用 |
|---|---|
JSON_UNESCAPED_UNICODE | 中文不轉 \uXXXX,直接輸出 UTF-8 (節省體積、可讀) |
JSON_UNESCAPED_SLASHES | 不轉義 / (前端模板常需) |
JSON_PRETTY_PRINT | 縮進換行格式化 |
JSON_NUMERIC_CHECK | 數字字符串 "123" → 123 (謹慎用,可能改變語義) |
JSON_PRESERVE_ZERO_FRACTION | 1.0 保持為 1.0 不變 1 |
JSON_FORCE_OBJECT | 索引數組強制輸出為對象 {} |
JSON_THROW_ON_ERROR | PHP 7.3+ 編碼失敗拋出異常 (而非返回 false) |
<?php
class User implements JsonSerializable {
private $id, $name, $password; // 密碼不應序列化
public function __construct(int $id, string $name, string $pwd) {
$this->id = $id; $this->name = $name; $this->password = $pwd;
}
public function jsonSerialize(): array {
return [
'id' => $this->id,
'name' => $this->name,
// password 故意省略
];
}
}
$user = new User(1, 'Admin', 'secret123');
echo json_encode($user, JSON_UNESCAPED_UNICODE); // {"id":1,"name":"Admin"}
?>
若必須在 PHP 5.1 或更老版本運行 (極罕見),請使用 **PECL JSON 擴展** 或引入 **Services_JSON** (PEAR 庫):**切勿複製手寫遞歸代碼**。
// composer require pear/services_json
require 'vendor/autoload.php';
$json = new Services_JSON(SERVICES_JSON_LOOSE_TYPE);
echo $json->encode($data);
| 缺陷 | 示例 | 後果 |
|---|---|---|
| 單引號非標準 | 'name': 'value' | 標準 JSON 必須雙引號,前端 JSON.parse 失敗 |
| 無 Unicode 轉義 | 中文直接輸出或亂碼 | 非 UTF-8 環境解析錯誤,體積膨脹 |
| 浮點數截斷 | 98.5000000001 → 98.5 | 精度丟失,金額計算災難 |
| 無法處理對象/資源 | new DateTime(), fopen() | 報錯或輸出空值 |
| 遞歸深度無限制 | 循環引用 $a['self']=&$a | 無限遞歸導致棧溢出 |
| 尾逗號風險 | {"a":1,} | 非標準 JSON,解析器拒絕 |
**永遠使用 json_encode()**。它是 C 實現、經過億級生產驗證、符合 RFC 8259 標準、支持所有 PHP 類型 (配合 JsonSerializable)、性能極高。手寫 JSON 編碼器是「重複造輪子」且「造出方輪子」的典型反面教材。