在php中的序列化与反序列化

序列化与反序列化的定义:

        序列化是指把对象转化为可传输的字节序列过程,而反序列化是指把字节序列还原为对象的过程。序列化和反序列化是数据持久化和网络传输中常用的技术手段,它们使得数据可以在不同平台、不同系统之间进行有效的存储和通信。

序列化详解:

  1. 概念解释:序列化是将对象的状态信息转换为可以存储或传输的形式(如字节流)的过程。这个过程可以通过不同的方式实现,例如使用Java内置的Serializable接口或者通过其他第三方库如JSON、XML等。

  2. 应用场景:序列化主要用于对象的持久化存储以及网络传输。在存储方面,它可以将对象保存到数据库或文件中;在网络传输方面,它允许对象通过网络发送到远程系统上,然后再反序列化成本地对象。

  3. 实现方法:在Java中,实现序列化的一种常见方法是让对象实现Serializable接口。这个接口虽然没有方法需要实现,但它标记了这个对象可以被JVM序列化和反序列化。

  4. 注意事项:在序列化过程中,静态字段和用transient关键字修饰的字段不会被序列化。此外,为了确保版本兼容性,建议显式定义serialVersionUID来控制版本的一致性。

  5. 性能考虑:选择序列化工具和技术时,需要考虑其性能和生成的数据大小。例如,Protobuf和MessagePack等工具提供了更小的消息大小和更快的序列化速度,适合在大规模分布式系统中使用。

反序列化详解:

  1. 概念解释:反序列化是将字节序列恢复成原有对象形态的过程。这一过程本质上是序列化的逆操作,要求能够准确地还原对象的状态。

  2. 应用场景:当数据从数据库或文件系统中读取出来,或者通过网络接收到序列化的数据后,客户端需要对这些数据进行反序列化,以重建原有的对象状态,进而执行业务逻辑处理。

  3. 实现方法:在Java中,使用ObjectInputStream类可以从输入流中读取字节序列,并将其反序列化为对象。这要求原始对象类实现了Serializable接口。

  4. 安全注意:反序列化过程可能存在安全风险,因为执行反序列化的过程中可能会运行恶意代码。因此,在处理不受信任的输入流时,应当格外小心,并采取相应的安全防护措施。

  5. 兼容性问题:如果序列化对象的类结构发生了变化(如添加了新的字段),可能导致反序列化失败。因此,管理serialVersionUID并合理设计类的结构变化对于保证反序列化的成功率至关重要。

总结而言,序列化与反序列化是数据处理和系统间通信不可或缺的技术。它们支持数据的持久化存储和跨网络传输,适用于多种场合,包括数据缓存、远程方法调用等。在选择具体的序列化技术时,应综合考虑性能、跨平台支持、安全性等因素,以适应不同的应用需求。

序列化与反序列化例子:
 

注意,当我们在序列化一个类的时候我们需要将该类定义出来。如下。

<?php
$raw = 'O:1:"A":1:{s:1:"a";s:1:"b";}';
var_dump(unserialize($raw));  //1进行反序列化并输出
echo serialize(unserialize($raw)); //2先进行反序列化再进行序列化。
?>

//输出结果1:
object(__PHP_Incomplete_Class)#1 (2) { ["__PHP_Incomplete_Class_Name"]=> string(1) "A" ["a"]=> string(1) "b" }

//输出结果2:
O:1:"A":1:{s:1:"a";s:1:"b";}

这段代码中的$raw字符串是一个序列化后的PHP对象。它包含了一个名为"A"的类的实例,该类有一个属性"a",其值为"b"。我们

$raw解析:

  1. O:1:"A":1:{s:1:"a";s:1:"b";}表示一个对象,其中:
    • O:1:"A"表示对象的类型为"A",并且该类型的类定义在当前命名空间中(即没有指定命名空间)。
    • 1表示对象的属性数量为1个。
    • {s:1:"a";s:1:"b";}表示对象的属性列表,其中:
      • s:1:"a"表示一个字符串类型的属性,属性名为"a",长度为1。
      • s:1:"b"表示另一个字符串类型的属性,属性名为"a"的值,长度为1。
  2. 反序列化$raw字符串后,会得到一个名为"A"的类的实例,该实例有一个属性"a",其值为"b"。

|我们通过对php的代码分析发现我们序列化了一个不存在的类“A“,但是当我们对$raw进行反序列化再序列化之后的输出和原来一样,这是为什么呢?
原因如下:

        可以发现PHP在遇到不存在的类时,会把不存在的类转换成__PHP_Incomplete_Class这种特殊的类,同时将原始的类名A存放在__PHP_Incomplete_Class_Name这个属性中,其余属性存放方式不变。而我们在序列化这个对象的时候,serialize遇到__PHP_Incomplete_Class这个特殊类会倒推回来,序列化成__PHP_Incomplete_Class_Name值为类名的类,我们看到的序列化结果不是O:22:"__PHP_Incomplete_Class_Name":2:{xxx}而是O:1:"A":1:{s:1:"a";s:1:"b";}

正常情况下的代码应该这样写:

<?php
class A {
    public $a;
}  //将A这个类定义出来

$raw = 'O:1:"A":1:{s:1:"a";s:1:"b";}';
$object = unserialize($raw);
var_dump($object);  //输出反序列化的结果
?>
//输出结果如下:
object(A)#1 (1) {
  ["a"]=>
  string(1) "b"
}

这表示我们成功地定义了类 "A",并通过反序列化得到了一个该类的实例,其中属性 $a 的值被正确设置为 "b"。

注意:

在实际应用中,序列化和反序列化数据时,确保在进行反序列化之前,相关的类已经被定义,以避免遇到__PHP_Incomplete_Class或其它潜在问题。

相关推荐

  1. php序列序列

    2024-06-17 20:16:02       10 阅读
  2. PHP序列

    2024-06-17 20:16:02       19 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-06-17 20:16:02       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-06-17 20:16:02       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-06-17 20:16:02       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-06-17 20:16:02       20 阅读

热门阅读

  1. 谈吐的艺术

    2024-06-17 20:16:02       8 阅读
  2. Mariadb/MySQL挂了且重启失败

    2024-06-17 20:16:02       7 阅读
  3. 软设之白盒测试

    2024-06-17 20:16:02       6 阅读
  4. 时区设置函数【man 3 tzset】

    2024-06-17 20:16:02       5 阅读
  5. 中国环保网元宇宙:开启绿色数字生活新篇章

    2024-06-17 20:16:02       9 阅读
  6. 哪些不得不记下的汇编指令

    2024-06-17 20:16:02       5 阅读