PHP JSON
JSON (JavaScript Object Notation) 是輕量級的資料交換格式,PHP 內建支援 JSON 編碼和解碼。
編碼 (json_encode)
<?php
// 陣列轉 JSON
$data = ['name' => 'Alice', 'age' => 25];
$json = json_encode($data);
echo $json; // {"name":"Alice","age":25}
// 索引陣列
$arr = ['apple', 'banana', 'cherry'];
echo json_encode($arr); // ["apple","banana","cherry"]
?>
編碼選項
json_encode() 的第二個參數可以傳入選項來調整輸出格式。多個選項可以用 | 運算符組合:
<?php
$data = ['name' => '小明', 'path' => '/home/user'];
// 預設輸出
echo json_encode($data);
// {"name":"\u5c0f\u660e","path":"\/home\/user"}
// 不跳脫 Unicode
echo json_encode($data, JSON_UNESCAPED_UNICODE);
// {"name":"小明","path":"\/home\/user"}
// 不跳脫斜線
echo json_encode($data, JSON_UNESCAPED_SLASHES);
// {"name":"\u5c0f\u660e","path":"/home/user"}
// 美化輸出
echo json_encode($data, JSON_PRETTY_PRINT);
// 組合選項
echo json_encode($data,
JSON_UNESCAPED_UNICODE |
JSON_UNESCAPED_SLASHES |
JSON_PRETTY_PRINT
);
?>
解碼 (json_decode)
json_decode() 將 JSON 字串轉換回 PHP 資料結構。第二個參數決定要轉成物件(預設)還是關聯陣列:
<?php
$json = '{"name":"Alice","age":25}';
// 解碼為物件(預設)
$obj = json_decode($json);
echo $obj->name; // Alice
// 解碼為關聯陣列
$arr = json_decode($json, true);
echo $arr['name']; // Alice
// 解碼深度和選項
$data = json_decode($json, true, 512, JSON_THROW_ON_ERROR);
?>
錯誤處理
當 JSON 格式錯誤時,json_decode() 預設會回傳 null 而不是拋出例外。有兩種方式可以偵測錯誤:
<?php
$invalidJson = '{"name": "Alice",}'; // 無效的 JSON
// 方法一:檢查 json_last_error()
$data = json_decode($invalidJson);
if (json_last_error() !== JSON_ERROR_NONE) {
echo "JSON 錯誤:" . json_last_error_msg();
}
// 方法二:使用 JSON_THROW_ON_ERROR(PHP 7.3+)
try {
$data = json_decode($invalidJson, true, 512, JSON_THROW_ON_ERROR);
} catch (JsonException $e) {
echo "JSON 錯誤:" . $e->getMessage();
}
?>
常見錯誤碼
| 常數 | 說明 |
|---|---|
JSON_ERROR_NONE | 沒有錯誤 |
JSON_ERROR_SYNTAX | 語法錯誤 |
JSON_ERROR_DEPTH | 超過最大深度 |
JSON_ERROR_UTF8 | UTF-8 編碼錯誤 |
驗證 JSON
<?php
function isValidJson(string $string): bool {
json_decode($string);
return json_last_error() === JSON_ERROR_NONE;
}
echo isValidJson('{"name":"Alice"}') ? 'Valid' : 'Invalid'; // Valid
echo isValidJson('invalid') ? 'Valid' : 'Invalid'; // Invalid
?>
處理 JSON 檔案
<?php
// 讀取 JSON 檔案
$json = file_get_contents('data.json');
$data = json_decode($json, true);
// 寫入 JSON 檔案
$data = ['users' => [
['name' => 'Alice', 'age' => 25],
['name' => 'Bob', 'age' => 30],
]];
file_put_contents(
'data.json',
json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)
);
?>
API 回應
<?php
// 設定 Content-Type
header('Content-Type: application/json; charset=utf-8');
// 成功回應
function jsonResponse($data, int $status = 200): void {
http_response_code($status);
echo json_encode([
'success' => true,
'data' => $data,
], JSON_UNESCAPED_UNICODE);
exit;
}
// 錯誤回應
function jsonError(string $message, int $status = 400): void {
http_response_code($status);
echo json_encode([
'success' => false,
'error' => $message,
], JSON_UNESCAPED_UNICODE);
exit;
}
// 使用
$users = [
['id' => 1, 'name' => 'Alice'],
['id' => 2, 'name' => 'Bob'],
];
jsonResponse($users);
?>
JsonSerializable 介面
實作 JsonSerializable 介面可以自訂物件轉換成 JSON 時的輸出內容,這在需要隱藏某些屬性(如密碼)或自訂格式時非常有用:
<?php
class User implements JsonSerializable {
public function __construct(
private int $id,
private string $name,
private string $email,
private string $password // 不想輸出
) {}
public function jsonSerialize(): array {
return [
'id' => $this->id,
'name' => $this->name,
'email' => $this->email,
// password 不包含
];
}
}
$user = new User(1, 'Alice', 'alice@example.com', 'secret');
echo json_encode($user);
// {"id":1,"name":"Alice","email":"alice@example.com"}
?>