序列化与反序列化的定义:
序列化是指把对象转化为可传输的字节序列过程,而反序列化是指把字节序列还原为对象的过程。序列化和反序列化是数据持久化和网络传输中常用的技术手段,它们使得数据可以在不同平台、不同系统之间进行有效的存储和通信。
序列化详解:
-
概念解释:序列化是将对象的状态信息转换为可以存储或传输的形式(如字节流)的过程。这个过程可以通过不同的方式实现,例如使用Java内置的
Serializable
接口或者通过其他第三方库如JSON、XML等。 -
应用场景:序列化主要用于对象的持久化存储以及网络传输。在存储方面,它可以将对象保存到数据库或文件中;在网络传输方面,它允许对象通过网络发送到远程系统上,然后再反序列化成本地对象。
-
实现方法:在Java中,实现序列化的一种常见方法是让对象实现
Serializable
接口。这个接口虽然没有方法需要实现,但它标记了这个对象可以被JVM序列化和反序列化。 -
注意事项:在序列化过程中,静态字段和用
transient
关键字修饰的字段不会被序列化。此外,为了确保版本兼容性,建议显式定义serialVersionUID
来控制版本的一致性。 -
性能考虑:选择序列化工具和技术时,需要考虑其性能和生成的数据大小。例如,Protobuf和MessagePack等工具提供了更小的消息大小和更快的序列化速度,适合在大规模分布式系统中使用。
反序列化详解:
-
概念解释:反序列化是将字节序列恢复成原有对象形态的过程。这一过程本质上是序列化的逆操作,要求能够准确地还原对象的状态。
-
应用场景:当数据从数据库或文件系统中读取出来,或者通过网络接收到序列化的数据后,客户端需要对这些数据进行反序列化,以重建原有的对象状态,进而执行业务逻辑处理。
-
实现方法:在Java中,使用
ObjectInputStream
类可以从输入流中读取字节序列,并将其反序列化为对象。这要求原始对象类实现了Serializable
接口。 -
安全注意:反序列化过程可能存在安全风险,因为执行反序列化的过程中可能会运行恶意代码。因此,在处理不受信任的输入流时,应当格外小心,并采取相应的安全防护措施。
-
兼容性问题:如果序列化对象的类结构发生了变化(如添加了新的字段),可能导致反序列化失败。因此,管理
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解析:
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。
- 反序列化
$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
或其它潜在问题。