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

PHP serialize vs json_encode:序列化與反序列化深度對比

     編輯:PHP 綜合知識

PHP 中 serialize()/unserialize() 與 json_encode()/json_decode() 是兩大序列化方案。它們在數據類型支援、跨語言互操作、性能、安全性上有本質差異。本文通過實測代碼詳細對比,給出選型指南。

基礎對比:對象與數組

$obj = new stdClass(); 
$obj->site = 'tantengvip'; 
$obj->owner = 'tuntun'; 
$obj->age = 5; 

$arr = [ 
    'site' => 'tantengvip', 
    'owner' => 'tuntun', 
    'age' => 5, 
];

serialize 方案

var_dump(serialize($obj)); 
// string(87) 'O:8:"stdClass":3:{s:4:"site";s:10:"tantengvip";s:5:"owner";s:6:"tuntun";s:3:"age";i:5;}' 

var_dump(unserialize(serialize($obj))); 
// object(stdClass)#2 (3) { ["site"]=> string(10) "tantengvip" ["owner"]=> string(6) "tuntun" ["age"]=> int(5) } 

var_dump(serialize($arr)); 
// string(74) 'a:3:{s:4:"site";s:10:"tantengvip";s:5:"owner";s:6:"tuntun";s:3:"age";i:5;}'

json 方案

var_dump(json_encode($obj)); 
// string(46) '{"site":"tantengvip","owner":"tuntun","age":5}' 

var_dump(json_decode(json_encode($obj))); 
// object(stdClass)#2 (3) { ["site"]=> string(10) "tantengvip" ["owner"]=> string(6) "tuntun" ["age"]=> int(5) } 

var_dump(json_decode(json_encode($obj), true)); // 第二參數 true → 關聯數組 
// array(3) { ["site"]=> string(10) "tantengvip" ["owner"]=> string(6) "tuntun" ["age"]=> int(5) }

核心差異:自定義類與私有屬性

class Test { 
    private $pri = 'pri'; 
    public $pub = 'pub'; 
    
    public function __construct() { 
        $this->pri = 'pri_construct'; 
        $this->pub = 'pub_construct'; 
    } 
} 

$test = new Test(); 

// serialize:保留類名、私有屬性、構造函數初始值 
var_dump(serialize($test)); 
// 'O:4:"Test":2:{s:9:"\0Test\0pri";s:13:"pri_construct";s:3:"pub";s:12:"pub_construct";}' 
var_dump(unserialize(serialize($test))); 
// object(Test)#2 (2) { ["pri":"Test":private]=> string(13) "pri_construct" ["pub"]=> string(12) "pub_construct" } 

// json:丟失私有屬性、類名變為 stdClass 
var_dump(json_encode($test)); 
// '{"pub":"pub_construct"}' 
var_dump(json_decode(json_encode($test))); 
// object(stdClass)#2 (1) { ["pub"]=> string(12) "pub_construct" }

綜合對比表

維度serializejson_encode
數據格式PHP 專有二進制兼容文本標準 JSON (RFC 8259)
跨語言不支援完美支援
類型保真度高(類名、私有/保護屬性、資源類型)低(僅公有屬性、stdClass、基本類型)
編碼要求任意編碼必須 UTF-8
可讀性差高
體積較大(含類型元信息)較小
性能稍快(C 級實現)稍慢(UTF-8 驗證、轉義)
安全性反序列化漏洞風險(__wakeup/__destruct 鏈)安全(無代碼執行)
魔術方法支援 __sleep/__wakeup/__serialize/__unserialize支援 JsonSerializable 接口
資源類型可序列化(句柄轉標識符)不支援(返回 null)

選型指南

  1. 緩存存儲:Redis/Memcached 值 → serialize(支援任意 PHP 類型、性能略優)
  2. API 輸出/異構系統通信:json_encode(標準、可讀、跨語言)
  3. Session 存儲:PHP 原生 Session 用 serialize,自定義 Session Handler 建議 json
  4. 隊列消息體:json(消費者可能非 PHP)
  5. 數據庫 JSON 字段:json_encode(MySQL 5.7+/PG JSONB 原生索引)
  6. 含私有屬性的領域對象持久化:serialize 或實現 JsonSerializable 手動控制輸出

安全警示:unserialize 反序列化漏洞

// 惡意構造的序列化字符串可觸發 __wakeup/__destruct 鏈 
// 導致任意代碼執行、文件讀寫、SSRF 等 
// 禁止對不可信數據調用 unserialize() 
// 必須使用: 
// 1. JSON 替代 
// 2. 如果必須用,PHP 7.0+ 提供 allowed_classes 參數 
$data = unserialize($untrusted, ['allowed_classes' => ['MySafeClass']]); 
// 3. 簽名驗證:存儲時 HMAC-SHA256 簽名,讀取時驗證後再反序列化

現代最佳實踐

  • 統一使用 json_encode/json_decode 作為默認序列化方案
  • 領域模型實現 JsonSerializable 接口精確控制輸出
  • 緩存層封裝 Cache::set($key, $value) 內部自動選擇(純數據用 json,對象用 serialize)
  • 遷移歷史 serialize 數據:讀取 → unserialize → json_encode → 重寫

理解兩者本質差異,根據場景選擇,既能享受 JSON 的通用性,又能在需要時利用 serialize 的類型保真度。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved