首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP JSON 操作完全指南:編碼、解碼、陣列轉換與巢狀處理

     編輯:PHP 相關知識

PHP JSON 操作完全指南:編碼、解碼、陣列轉換與巢狀處理

JSON (JavaScript Object Notation) 是現代 Web 開發中最通用的資料交換格式。PHP 內建 json_encode、json_decode 兩大核心函數,支援陣列、物件、巢狀結構的雙向轉換。本文系統梳理常用操作、參數選項、編碼陷阱與最佳實踐。

核心函數速覽

基礎操作範例

1. 陣列/物件編碼為 JSON

<?php
$data = [
    'name'    => '張三',
    'age'     => 28,
    'skills'  => ['PHP', 'JavaScript', 'MySQL'],
    'address' => (object)['city' => '台北', 'zip' => '100'],
];

// 基礎編碼
$json = json_encode($json);
echo $json;
// {"name":"\u5f20\u4e09","age":28,"skills":["PHP","JavaScript","MySQL"],"address":{"city":"\u53f0\u5317","zip":"100"}}

// 推薦參數:可讀 + 中文不轉義 + 斜線不轉義
$json = json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
echo $json;
/* 輸出:
{
    "name": "張三",
    "age": 28,
    "skills": ["PHP", "JavaScript", "MySQL"],
    "address": {"city": "台北", "zip": "100"}
}
*/

2. JSON 解碼為 PHP 變量

<?php
$json = '{"name":"張三","age":28,"skills":["PHP","JS"],"address":{"city":"台北"}}';

// 解碼為物件 (預設)
$obj = json_decode($json);
echo $obj->name;           // 張三
echo $obj->address->city;  // 台北

// 解碼為關聯陣列 (推薦,操作更直觀)
$arr = json_decode($json, true);
echo $arr['name'];              // 張三
echo $arr['address']['city'];   // 台北

// 訪問巢狀陣列
foreach ($arr['skills'] as $skill) {
    echo $skill . "\n";
}

進階場景處理

1. 巢狀 JSON 轉多維陣列 (遞歸)

<?php
function jsonToArrayRecursive($data)
{
    if (is_object($data)) {
        $data = get_object_vars($data);
    }
    if (!is_array($data)) {
        return $data;
    }
    return array_map('jsonToArrayRecursive', $data);
}

$json = '{"user":{"profile":{"name":"李四","meta":{"vip":true,"level":5}}}}';
$obj = json_decode($json);
$arr = jsonToArrayRecursive($obj);
print_r($arr);
/*
Array
(
    [user] => Array
        (
            [profile] => Array
                (
                    [name] => 李四
                    [meta] => Array
                        (
                            [vip] => 1
                            [level] => 5
                        )
                )
        )
)
*/

2. 大整數精度處理 (PHP 5.4+)

<?php
$json = '{"id": 9007199254740993, "big": "9007199254740993"}'; // 超過 JS 安全整數範圍

// 預設會以浮點數/科學記號表示,可能失真
var_dump(json_decode($json)); 
// object(stdClass)#1 (2) { ["id"]=> float(9.007199254741E+15) ["big"]=> string(16) "9007199254740993" }

// 使用 JSON_BIGINT_AS_STRING 保持字串精度
$arr = json_decode($json, true, 512, JSON_BIGINT_AS_STRING);
var_dump($arr['id']); // string(16) "9007199254740993" ✅

3. 錯誤處理與驗證

<?php
function safeJsonDecode($json, $assoc = true)
{
    $result = json_decode($json, $assoc);
    switch (json_last_error()) {
        case JSON_ERROR_NONE:
            return $result;
        case JSON_ERROR_DEPTH:
            throw new Exception('JSON 層級過深');
        case JSON_ERROR_SYNTAX:
            throw new Exception('JSON 語法錯誤: ' . json_last_error_msg());
        case JSON_ERROR_UTF8:
            throw new Exception('UTF-8 編碼錯誤');
        default:
            throw new Exception('JSON 解析失敗: ' . json_last_error_msg());
    }
}

try {
    $data = safeJsonDecode('{"invalid: json}');
} catch (Exception $e) {
    error_log($e->getMessage());
}

4. JSONP 回調輸出 (跨域老方案)

<?php
$callback = $_GET['callback'] ?? '';
$data = ['status' => 'ok', 'time' => time()];

if ($callback) {
    // 簡單驗證回調名稱安全性
    if (preg_match('/^[a-zA-Z_][\w.]*$/', $callback)) {
        header('Content-Type: application/javascript');
        echo $callback . '(' . json_encode($data, JSON_UNESCAPED_UNICODE) . ');';
        exit;
    }
}
header('Content-Type: application/json');
echo json_encode($data, JSON_UNESCAPED_UNICODE);

常見編碼選項組合推薦

<?php
// API 回應標準配置
$flags = JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP;
// JSON_HEX_* 系列:將特殊字元轉為 \uXXXX,增強 XSS 防護 (配合正確 Content-Type)

// 儲存到資料庫/檔案 (緊湊)
$flags = JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES;

// 除錯/日誌輸出 (可讀)
$flags = JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES;

效能與記憶體考量

  • json_encode 時間複雜度 O(n),大型陣列 (10萬+ 元素) 可能耗時百毫秒級
  • 避免在循環中重複編碼相同資料,預先編碼緩存
  • 超大 JSON 流式處理:考慮 JsonStreamingParser 或分批處理
  • PHP 7.3+ 引入 JSON_THROW_ON_ERROR 旗標,可拋出異常替代錯誤碼檢查

最佳實踐清單

  1. 輸出 JSON 時:始終設置 `header('Content-Type: application/json; charset=utf-8')`
  2. 中文內容:必加 `JSON_UNESCAPED_UNICODE`,減小體積、提升可讀性
  3. URL/路徑包含斜線:加 `JSON_UNESCAPED_SLASHES` 避免 `\/` 干擾前端解析
  4. 安全性:API 端加 `JSON_HEX_TAG|JSON_HEX_APOS|JSON_HEX_QUOT|JSON_HEX_AMP` 防禦 XSS
  5. 解碼時:習慣用 `$assoc = true` 直接得到陣列,避免物件/陣列混用困惑
  6. 外部輸入:必須 `json_last_error()` 檢查,防惡意畸形 JSON 攻擊
  7. 資料庫存儲:MySQL 5.7+ / PostgreSQL 9.4+ 原生支援 JSON 型別,優先使用而非 TEXT

總結

PHP JSON 操作核心只有兩個函數,但選項組合、錯誤處理、編碼細節決定了介面的穩健度。掌握 JSON_UNESCAPED_UNICODE、JSON_BIGINT_AS_STRING、json_last_error 機制,並建立統一的編碼/解碼封裝函數,即可應對從簡單 API 到複雜資料交換的各類場景。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
函數用途關鍵參數
json_encode($value, $flags, $depth)PHP 變量 → JSON 字串JSON_PRETTY_PRINT, JSON_UNESCAPED_UNICODE, JSON_UNESCAPED_SLASHES
json_decode($json, $assoc, $depth, $options)JSON 字串 → PHP 變量$assoc=true 返回關聯陣列, JSON_BIGINT_AS_STRING
json_last_error()獲取最後錯誤代碼JSON_ERROR_NONE, JSON_ERROR_SYNTAX, JSON_ERROR_UTF8...
json_last_error_msg()獲取錯誤描述 (PHP 5.5+)返回可讀字串