1. 程式人生 > >serialize序列化和json

serialize序列化和json

【序列化的概念】

序列化是將物件狀態轉換為可保持或可傳輸的格式的過程。與序列化相對的是反序列化,它將流轉換為物件。這兩個過程結合起來,可以輕鬆地儲存和傳輸資料。

將物件的狀態資訊轉換為可以儲存或傳輸的窗體的過程。 在序列化期間,物件將其當前狀態寫入到臨時或永續性儲存區。以後,可以通過從儲存區中讀取或反序列化物件的狀態,重新建立該物件。

通常,物件例項的所有欄位都會被序列化,這意味著資料會被表示為例項的序列化資料。這樣,能夠解釋該格式的程式碼有可能能夠確定這些資料的值,而不依賴於該成員的可訪問性。類似地,反序列化從序列化的表示形式中提取資料,並直接設定物件狀態,這也與可訪問性規則無關。 對於任何可能包含重要的安全性資料的物件,如果可能,應該使該物件不可序列化。如果它必須為可序列化的,請嘗試生成特定欄位來儲存不可序列化的重要資料。如果無法實現這一點,則應注意該資料會被公開給任何擁有序列化許可權的程式碼,並確保不讓任何惡意程式碼獲得該許可權。

【JSON的概念】

JSON,JavaScript Object Notation,一種更輕、更友好的用於介面(AJAX、REST等)資料交換的格式。 JSON是結構化資料序列化的文字格式,作為XML的一種替代品,用於表示客戶端與伺服器間資料交換有效負載的格式。它是從ECMAScript語言標準衍生而來的。JSON的設計目標是使它成為小的、輕便的、文字的,而且是JavaScript的一個子集。

【長度的比較】

如下一段程式碼,顯示了對陣列和物件編碼後生成的字串及其長度

class Foo {

    public $int = 1;
    public $bool = TRUE;
public $array = array(array(1), 2 => 'test', 'string'); public function test($flag) { echo $flag, 'test function for Foo <br />'; } public static function output($str) { echo $str, '<br />'; } public static function compare_serialize_and_json(
$data) { $serialize_str = serialize($data); self::output('序列化後的值:' . $serialize_str . "; length=" . strlen($serialize_str)); $json_str = json_encode($data); self::output('JSON後的值:' . $json_str . "; length=" . strlen($json_str)); } } $test_data = array('wwww' => 0, 'phppan' => 1, 'com' => 2); //序列化陣列 echo '陣列:<br />'; Foo::compare_serialize_and_json($test_data); $foo = new Foo(); echo '物件:<br />'; Foo::compare_serialize_and_json($foo);

輸出:

陣列:
序列化後的值:a:3:{s:4:"wwww";i:0;s:6:"phppan";i:1;s:3:"com";i:2;}; length=52
JSON後的值:{"wwww":0,"phppan":1,"com":2}; length=29
物件:
序列化後的值:O:3:"Foo":3:{s:3:"int";i:1;s:4:"bool";b:1;s:5:"array";a:3:{i:0;
    a:1:{i:0;i:1;}i:2;s:4:"test";i:3;s:6:"string";}}; length=111
JSON後的值:{"int":1,"bool":true,"array":{"0":[1],"2":"test","3":"string"}}; length=63

很明顯的長度區別,serialize在編碼後大概是json的兩倍

原因:

  • serialize後字串包含了子串的長度,這可能是速度方面的優化,典型的空間換時間,但是它本身還是太重了。
  • serialize有更加詳細的型別區分,而json只有四種類型,並且是以簡單的符號表示。

【速度的比較】

以程式碼說明問題,如下比較速度的程式碼:

$max_index = 10;
ini_set("memory_limit","512M");
$array = array_fill(0, 1000000, rand(1, 9999));

echo 'serialize:<br />';
$start = xdebug_time_index();
for ($i = 0;  $i < $max_index; $i++) {
    $str = serialize($array);
}
$end = xdebug_time_index();
echo $end - $start, '<br />';

echo 'json:<br />';
$start = xdebug_time_index();
for ($i = 0;  $i < $max_index; $i++) {
    $str = json_encode($array);
}
$end = xdebug_time_index();
echo $end - $start, '<br />';
unset($array, $str);

輸出:

serialize:
9.5371007919312
json:
1.4313209056854

serialize的速度在大資料量的情況下比json差了快一個數量級。

從上面兩點看,json不管是在速度還是在生成的字串的大小上都比serialize要好,那為什麼serialize還要存在呢? 原因在下面這個點:實現的功能。

【處理物件】

如下程式碼:

header("Content-type:text/html;charset=utf8");
class Foo {
     public function test($flag) {
        echo $flag, 'test function for Foo <br />';
    }
}

$foo = new Foo();

echo '反序列化測試:<br />';
$foo->test(1);
$serialize_str = serialize($foo);
$obj = unserialize($serialize_str);
$obj->test(2);

$foo->test(1);
$json_str = json_encode($foo);
$obj = json_decode($json_str);
$obj->test(2);
die();

輸出:

反序列化測試:
1test function for Foo
2test function for Foo
1test function for Foo 

( ! ) Fatal error: Call to undefined method stdClass::test()

json無法處理物件方法等資料。

【使用範圍】

  • 序列化使用serialize,特別是物件的儲存。這是其存在的意義。
  • 與物件無關的資料儲存可以使用json,如包含大量數字的陣列等。只是當遇到這種情況,我們需要做的可能是重構資料庫了。
  • 資料交換時使用JSON,這也是其定義所在。
  • 目前JSON是能用於UTF-8編碼的資料。
轉自 http://www.phppan.com/2011/03/serialize-json/

有時候需要把一個物件在網路上傳輸,為了方便傳輸,可以把整個物件轉化為二進位制串,等到達另一端時,再還原為原來的物件,這個過程稱之為序列化(也叫序列化), 就像我們現在想把一輛汽車通過輪船運到美國去,因為汽車的體積比較大,我們可以把汽車拆開成小的部件,然後我們把這些部件通過輪般運到美國去,到了美國再把這些部件組裝回汽車。

有兩種情況我們必須把物件序列化,第一種情況就是把一個物件在網路中傳輸的時候要將物件序列化,第二種情況就是把物件寫入檔案或是資料庫的時候用到序列化。

序列化有兩個過程,一個是序列化,就是把物件轉化為二進位制的字串,我們使用serialize()函式來序列化一個物件,另一個是反序列化,就是把物件轉化的二進位制字串再轉化為物件, 我們使用unserialize()函式來反序列化一個物件。

PHP中serialize()函式的引數為物件名,返回值為一個字串,Serialize()返回的字串含義模糊,一般我們不會解析這個串來得到物件的資訊,我們只要把返回來的這個字串傳到網路另一端或是儲存到檔案中即可。

PHP中unserialize()函式來反序列化物件,這個函式的引數即為serialize()函式的返回值,輸出當然是重新組織好的物件。

  1. <?  
  2. class Person  
  3. {  
  4.     //下面是人的成員屬性
  5.     var$name;    //人的名子
  6.     var$sex;    //人的性別
  7.     var$age;    //人的年齡
  8.     //定義一個構造方法引數為屬性姓名$name、性別$sex和年齡$age進行賦值
  9.     function __construct($name = ""$sex = ""$age = "") {  
  10.         $this->name = $name;  
  11.         $this->sex = $sex;  
  12.         $this->age = $age;  
  13.     }  
  14.     //這個人可以說話的方法, 說出自己的屬性
  15.     function say() {  
  16.         echo"我的名子叫:" . $this