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

PHP JSON 處理完全指南:json_encode/json_decode 進階用法、陣列轉換陷阱與常見錯誤避坑

     編輯:PHP 相關知識

PHP JSON 處理完全指南:json_encode/json_decode 進階用法、陣列轉換陷阱與常見錯誤避坑

自 PHP 5.2 起,json_encode() 與 json_decode() 成為原生擴展,是現代 PHP 開發中資料交換、API 介接、配置儲存的核心工具。本文系統整理 JSON 編碼/解碼的進階特性、索引陣列與關聯陣列的轉換差異、類別屬性序列化行為、強制輸出格式技巧,以及 json_decode 常見失敗原因與解決方案。

一、json_encode() 核心用法與輸出範例

1. 基礎關聯陣列編碼

<?php
$arr = ['a'=>1, 'b'=>2, 'c'=>3, 'd'=>4, 'e'=>5];
echo json_encode($arr);
// 輸出:{"a":1,"b":2,"c":3,"d":4,"e":5}
?>

2. 物件屬性編碼(僅公開屬性)

<?php
$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 僅序列化 public 屬性。private、protected、常數、方法皆會被忽略。

3. 編碼限制:必須為 UTF-8

注意: JSON 標準強制要求 UTF-8 編碼。若輸入資料包含非 UTF-8 字元(如 GB2312 中文、ISO-8859-1 西文),json_encode 會返回 null 或空字串。請在編碼前使用 mb_convert_encoding() 或 iconv() 轉換為 UTF-8。

二、索引陣列 vs 關聯陣列:輸出格式的決定性差異

JavaScript 無關聯陣列概念,因此 PHP 的 json_encode 採用以下規則:

  • 索引陣列(連續數字鍵 0,1,2...) → 輸出 JSON 陣列 [...]
  • 關聯陣列(字串鍵或非連續數字鍵) → 輸出 JSON 物件 {...}

範例對比

<?php
// 索引陣列
$indexed = ['one', 'two', 'three'];
echo json_encode($indexed); // ["one","two","three"]

// 關聯陣列(字串鍵)
$assoc = ['1'=>'one', '2'=>'two', '3'=>'three'];
echo json_encode($assoc);   // {"1":"one","2":"two","3":"three"}

// 關聯陣列(非連續數字鍵)
$gap = [0=>'a', 2=>'b', 5=>'c'];
echo json_encode($gap);     // {"0":"a","2":"b","5":"c"}
?>

強制索引陣列輸出為物件

<?php
$arr = ['one', 'two', 'three'];

// 方法 1:型別轉換
echo json_encode((object)$arr); // {"0":"one","1":"two","2":"three"}

// 方法 2:JSON_FORCE_OBJECT 旗標(PHP 5.3+)
echo json_encode($arr, JSON_FORCE_OBJECT); // 同上
?>

三、類別序列化深度解析

<?php
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"}
?>

序列化規則總結:

  • ✅ public 實例屬性 → 包含
  • ❌ private/protected 屬性 → 忽略
  • ❌ 類別常數(const) → 忽略
  • ❌ 靜態屬性(static) → 忽略
  • ❌ 方法 → 忽略

對策: 若需序列化受保護屬性,實作 JsonSerializable 介面並自訂 jsonSerialize() 方法。

四、json_decode() 解碼與陣列/物件控制

1. 預設返回 stdClass 物件

<?php
$json = '{"a":1,"b":2,"c":3,"d":4,"e":5}';
$obj = json_decode($json);
echo $obj->a; // 1
var_dump($obj); // object(stdClass)#1 (5) { ["a"]=>int(1) ... }
?>

2. 強制返回關聯陣列(第二參數 true)

<?php
$arr = json_decode($json, true);
var_dump($arr);
// array(5) { ["a"]=>int(1) ["b"]=>int(2) ... }
?>

五、json_decode() 五大常見失敗原因(返回 null)

錯誤 JSON 範例錯誤原因修正
{ 'bar': 'baz' }字串分隔符必須用雙引號,不可用單引號{ "bar": "baz" }
{ bar: "baz" }鍵名(冒號左側)必須用雙引號包裹{ "bar": "baz" }
{ "bar": "baz", }最後一個鍵值對後不能有尾隨逗號{ "bar": "baz" }
"Hello World"JSON 頂層必須是物件或陣列,純字串/數值無效包裹為 ["Hello World"] 或 {"msg":"Hello World"}
12345同上,頂層不可為裸露數值包裹為陣列或物件

六、實務除錯技巧

<?php
$json = '...'; // 來源資料
$data = json_decode($json, true);

if (json_last_error() !== JSON_ERROR_NONE) {
    // 詳細錯誤訊息
    $errors = [
        JSON_ERROR_DEPTH => '堆疊深度超過限制',
        JSON_ERROR_STATE_MISMATCH => '狀態不匹配(無效或畸形 JSON)',
        JSON_ERROR_CTRL_CHAR => '控制字元錯誤',
        JSON_ERROR_SYNTAX => '語法錯誤(最常見)',
        JSON_ERROR_UTF8 => '非 UTF-8 編碼字元',
    ];
    throw new Exception('JSON 解析失敗:' . ($errors[json_last_error()] ?? '未知錯誤'));
}
?>

總結

  • json_encode:注意 UTF-8 編碼、關聯陣列輸出為物件、僅序列化 public 屬性。
  • json_decode:預設回物件,加 true 回關聯陣列;嚴格遵循 JSON 標準(雙引號、無尾隨逗號、頂層為物件/陣列)。
  • 除錯時善用 json_last_error() 與 json_last_error_msg()(PHP 5.5+)快速定位問題。
  • 複雜物件序列化請實作 JsonSerializable 介面,掌控輸出結構。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved