對於那些剛剛接觸PHP (從 PHP 3.05 開始)為保存對象提供了一組序列化和反序列化的函數:serialize、unserialize。不過在 PHP 手冊中對這兩個函數的說明僅限於如何使用,而對序列化結果的格式卻沒做任何說明。
因此,這對在其他語言中實現PHP序列化格式來說,就比較麻煩了。雖然以前也搜集了一些其他語言實現的 PHP 序列化的程序,不過這些實現都不完全,當序列化或反序列化一些比較復雜的對象時,就會出錯了。
於是我決定寫一份關於PHP序列化格式詳解的文檔(也就是這一篇文檔),以便在編寫其他語言實現的 php 序列化程序時能有一個比較完整的參考。
這篇文章中所寫的內容是我通過編寫程序測試和閱讀 PHP 源代碼得到的,所以,我不能 100% 保證所有的內容都是正確的,不過我會盡量保證我所寫下的內容的正確性,對於我還不太清楚的地方,我會在文中明確指出,也希望大家能夠給予補充和完善。
PHP序列化格式後的內容是簡單的文本格式,但是對字母大小寫和空白(空格、回車、換行等)敏感,而且字符串是按照字節(或者說是 8 位的字符)計算的,因此,更合適的說法是 PHP 序列化後的內容是字節流格式。
因此用其他語言實現時,如果所實現的語言中的字符串不是字節儲存格式,而是 Unicode 儲存格式的話,序列化後的內容不適合保存為字符串,而應保存為字節流對象或者字節數組,否則在與 PHP 進行數據交換時會產生錯誤。
PHP 對不同類型的數據用不同的字母進行標示,Yahoo 開發網站提供的 Using Serialized PHP with Yahoo! Web Services 一文中給出所有的字母標示及其含義:
a - array
b - boolean
d - double
i - integer
o - common object
r - reference
s - string
C - custom object
O - class
N - null
R - pointer reference
U - unicode string
N 表示的是 NULL,而 b、d、i、s 表示的是四種標量類型,目前其它語言所實現的PHP序列化格式程序基本上都實現了對這些類型的序列化和反序列化,不過有一些實現中對 s (字符串)的實現存在問題。
a、O 屬於最常用的復合類型,大部分其他語言的實現都很好的實現了對 a 的序列化和反序列化,但對 O 只實現了 PHP4 中對象序列化格式,而沒有提供對 PHP 5 中擴展的對象序列化格式的支持。
r、R 分別表示對象引用和指針引用,這兩個也比較有用,在序列化比較復雜的數組和對象時就會產生帶有這兩個標示的數據,後面我們將詳細講解這兩個標示,目前這兩個標示尚沒有發現有其他語言的實現。
C 是 PHP5 中引入的,它表示自定義的對象序列化方式,盡管這對於其它語言來說是沒有必要實現的,因為很少會用到它,但是後面還是會對它進行詳細講解的。
U 是 PHP6 中才引入的,它表示 Unicode 編碼的字符串。因為 PHP6 中提供了 Unicode 方式保存字符串的能力,因此它提供了這種PHP序列化格式字符串的格式,不過這個類型 PHP5、PHP4 都不支持,而這兩個版本目前是主流,因此在其它語言實現該類型時,不推薦用它來進行序列化,不過可以實現它的反序列化過程。在後面我也會對它的格式進行說明。
最後還有一個 o,這也是我唯一還沒弄清楚的一個數據類型標示。這個標示在 PHP3 中被引入用來序列化對象,但是到了 PHP4 以後就被 O 取代了。在 PHP3 的源代碼中可以看到對 o 的序列化和反序列化與數組 a 基本上是一樣的。但是在 PHP4、PHP5 和 PHP6 的源代碼中PHP序列化格式部分裡都找不到它的影子,但是在這幾個版本的反序列化程序源代碼中卻都有對它的處理,不過把它處理成什麼我還沒弄清楚。因此對它暫時不再作更多說明了。