自 PHP 5.2 起內建 json_encode() 與 json_decode(),成為資料交換標準工具。本文系統整理編碼規則、陣列/物件轉換差異、類別序列化行為、解碼選項與常見錯誤,助你避開坑洞。
<?php
$arr = array('a'=>1, 'b'=>2, 'c'=>3, 'd'=>4, 'e'=>5);
echo json_encode($arr); // {"a":1,"b":2,"c":3,"d":4,"e":5}
$obj = new stdClass();
$obj->body = 'another post';
$obj->id = 21;
$obj->approved = true;
$obj->favorite_count = 1;
$obj->status = null;
echo json_encode($obj);
// {"body":"another post","id":21,"approved":true,"favorite_count":1,"status":null}
?>
json_encode() 參數必須為 UTF-8,否則中文會變成空字串或 null。若資料來源為 GB2312、Big5 或 ISO-8859-1,請先用 mb_convert_encoding() 或 iconv() 轉碼。
JavaScript 無關聯陣列概念,PHP 依鍵名類型決定 JSON 結構:
| PHP 陣列類型 | 鍵名特徵 | JSON 輸出 | 結構 |
|---|---|---|---|
| 索引陣列 | 連續數字鍵 0,1,2… | ["one","two","three"] |
Array [] |
| 關聯陣列 | 字串鍵或非連續數字鍵 | {"1":"one","2":"two"} |
Object {} |
$arr = ['one', 'two', 'three'];
echo json_encode((object)$arr); // {"0":"one","1":"two","2":"three"}
echo json_encode($arr, JSON_FORCE_OBJECT); // 同結果
class Foo {
const ERROR_CODE = '404';
public $public_ex = 'this is public';
private $private_ex = 'this is private!';
protected $protected_ex = 'this should be protected';
public function getErrorCode() { return self::ERROR_CODE; }
}
$foo = new Foo;
echo json_encode($foo); // {"public_ex":"this is public"}
注意:常數、私有/受保護屬性、方法均不會被編碼。若需完整序列化,請實作 JsonSerializable 介面(PHP 5.4+)。
$json = '{"a":1,"b":2,"c":3,"d":4,"e":5}';
// 預設回傳 stdClass 物件
$obj = json_decode($json);
echo $obj->a; // 1
// 第二參數 true 強制回傳關聯陣列
$arr = json_decode($json, true);
echo $arr['a']; // 1
| 錯誤 JSON | 錯誤原因 |
|---|---|
{ 'bar': 'baz' } | 鍵名與字串值必須用雙引號,不可單引號 |
{ bar: "baz" } | 鍵名必須加雙引號 |
{ "bar": "baz", } | 最後一個值不能有尾隨逗號 |
json_decode("Hello World") 回傳 null:JSON 須為物件或陣列結構,純字串/數值無效。$depth 調整。PHP_INT_MAX)會轉為浮點數,精度可能損失,建議以字串傳遞 ID。json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),避免中文被轉義、斜線被轉義。true 取得陣列,配合 isset()、array_key_exists() 更安全。json_last_error()、json_last_error_msg() 取得詳細錯誤資訊。更多 PHP 字串處理與資料交換技巧,請參考專題:《PHP 字串用法總結》、《PHP 陣列操作技巧大全》。