PHP序列化对象(serialize)和json_encode对比

今天突然看到一本书上讲的是序列化,挺感兴趣的研究了一下,贴一下研究成果
,首先上测试代码:
分别测试了序列化和json_encode对对象和数组的编码测试,如下:

<?php
class person
{
    protected $name='张三';
    protected $age=22;
    protected $job='admin';

    public function say()
    {
        echo '这是对象说的一句话';
    }
}

$arr=array(
    'name'=>'李四',
    'age'=>25,
    'job'=>'student'
);

$per=new person();
$obj=serialize($per);
echo '---------------------序列化对象-----------------------'.PHP_EOL;
echo ($obj).PHP_EOL;
echo PHP_EOL;
echo '---------------------反序列化对象-----------------------'.PHP_EOL;
var_dump(unserialize($obj)).PHP_EOL;
echo PHP_EOL;
echo '---------------------序列化数组-----------------------'.PHP_EOL;
var_dump($arr).PHP_EOL;
echo PHP_EOL;
echo '---------------------json串化数组-----------------------'.PHP_EOL;
echo $narr=json_encode($arr).PHP_EOL;
echo PHP_EOL;
echo '---------------------json反串化数组-----------------------'.PHP_EOL;
var_dump(json_decode($narr)).PHP_EOL;
echo PHP_EOL;
echo '---------------------json串化对象-----------------------'.PHP_EOL;
var_dump(json_encode($per)).PHP_EOL;
echo PHP_EOL;
?>

结果如下:

---------------------序列化对象-----------------------
O:6:"person":3:{s:7:"*name";s:6:"张三";s:6:"*age";i:22;s:6:"*job";s:5:"admin";}

---------------------反序列化对象-----------------------
class person#2 (3) {
  protected $name =>
  string(6) "张三"
  protected $age =>
  int(22)
  protected $job =>
  string(5) "admin"
}

---------------------序列化数组-----------------------
array(3) {
  'name' =>
  string(6) "李四"
  'age' =>
  int(25)
  'job' =>
  string(7) "student"
}

---------------------json串化数组-----------------------
{"name":"\u674e\u56db","age":25,"job":"student"}

---------------------json反串化数组-----------------------
class stdClass#2 (3) {
  public $name =>
  string(6) "李四"
  public $age =>
  int(25)
  public $job =>
  string(7) "student"
}

---------------------json串化对象-----------------------
string(2) "{}"

在这里要说说序列化的最重要的魔术方法 __sleep()和__wakeup(),也是和json编码有实质区别的地方。
还是举例说明:

<?php
class test
{
    public $a=1;
    
    public $b=2;

    public function __sleep()
    {
        return ['a','b'];
    }

    public function __wakeup()
    {
        echo $this->a.PHP_EOL;
    }
}
$test=new test();
unserialize(serialize($test));


//cli结果
localhost:test yehua$ php func.php
1
localhost:test yehua$ 

解释一下上面的例子,当执行类的序列化的同时,系统会自动调用sleep函数 保存当前返回数据里面的值,这些值可以是当前类属性的值,可以理解为冻结。当序列化解除的时候 系统会调用wakeup 通过该函数可以让类继续工作 ,可以理解为苏醒。我看也来看看苏醒之后能做什么

<?php
class test
{
    public $a=1;
    private $v=2;
    public static $c=3;
    const D=4;
    public function write()
    {
        echo 'write code'.PHP_EOL;
    }
    public static function speak()
    {
        echo 'speaking'.PHP_EOL;
    }

    public function __sleep()
    {
        return ['a','v','c','D'];
    }

    public function __wakeup()
    {
        self::speak();
        $this->write();
    }
}
$test=new test();
var_dump($res=serialize($test)).PHP_EOL;
echo '-------------------------'.PHP_EOL;
var_dump(unserialize($res)).PHP_EOL;


//cli 结果
localhost:test yehua$ php func.php
/Users/yehua/Desktop/test/func.php:29:
string(65) "O:4:"test":4:{s:1:"a";i:1;s:7:"\000test\000v";i:2;s:1:"c";N;s:1:"D";N;}"
-------------------------
speaking
write code
/Users/yehua/Desktop/test/func.php:31:
class test#2 (4) {
  public $a =>
  int(1)
  private $v =>
  int(2)
  public $c =>
  NULL
  public $D =>
  NULL
}

苏醒之后可以调用自身的方法。如果我们有类似冻结-苏醒这种需求可以试试

我们再看看更多情况下的序列化表现

<?php
class test
{
	//普通变量
    public $a=1;
    //私有变量
    private $v=2;
    //静态变量
    public static $c=3;
    //常量
    const D=4;
    //公共方法
    public function write()
    {
        echo 'write code';
    }
    //静态方法
    public static function speak()
    {
        echo 'speaking';
    }
}
$test=new test();
var_dump($res=serialize($test)).PHP_EOL;
echo '-------------------------';
var_dump(unserialize($res)).PHP_EOL;


// cli 结果
/Users/yehua/Desktop/test/func.php:23:
string(45) "O:4:"test":2:{s:1:"a";i:1;s:7:"\000test\000v";i:2;}"
-------------------------/Users/yehua/Desktop/test/func.php:25:
class test#2 (2) {
  public $a =>
  int(1)
  private $v =>
  int(2)
}

测试完毕之后发现,序列化只保存常规变量;

我们再试试继承

<?php
class test
{
    public $a=1;
    private $v=2;
}

class T extends test
{

}
$test=new T();
var_dump($res=serialize($test)).PHP_EOL;
echo '-------------------------'.PHP_EOL;
var_dump(unserialize($res)).PHP_EOL;


//cli结果
/Users/yehua/Desktop/test/func.php:13:
string(42) "O:1:"T":2:{s:1:"a";i:1;s:7:"\000test\000v";i:2;}"
-------------------------
/Users/yehua/Desktop/test/func.php:15:
class T#2 (2) {
  public $a =>
  int(1)
  private $v =>
  int(2)
}

看来单继承是没有问题的,我们再试试多继承

<?php
class test
{
    public $a=1;
    private $v=2;
}

trait testb
{
    public $c=2;
}
class T extends test
{
    use testb;
}
$test=new T();
var_dump($res=serialize($test)).PHP_EOL;
echo '-------------------------'.PHP_EOL;
var_dump(unserialize($res)).PHP_EOL;


// 结果
string(54) "O:1:"T":3:{s:1:"a";i:1;s:7:"\000test\000v";i:2;s:1:"c";i:2;}"
-------------------------
/Users/yehua/Desktop/test/func.php:19:
class T#2 (3) {
  public $a =>
  int(1)
  private $v =>
  int(2)
  public $c =>
  int(2)
}

也是没问题的

总结一下:
序列化可以同时实现对对象和数组实现保存,更重要的是,序列化不同于json编码,他还保存数据的类型。*注意下只能保存对象的属性,不能保存方法。
json_encode 可以保存数组,但是不能保存对象。而且反编码之后不会恢复原有数据结构

因此,序列化在redis 和数据库中有很大的作用 可以很好的保存数据和类型。更重要的是保存状态。是一种临时冻结的策略。
*最后提一下速度问题。序列化的速度大概比json_encode 慢一倍左右。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值