我正在使用 php serialize() 序列化 php 对象。但是,它会在受保护成员变量的结果中添加空字节。然后,该结果作为消息传递到 Amazon SQS 队列。问题是 SQS 不支持消息正文中的空字节。有什么办法可以摆脱空字节。我必须确保结果在另一端仍然不可序列化。
我在尝试序列化对象时遇到了同样的问题。
如Michael - sqlbot评论中所述,
base64_encode
函数正确处理NUL字节。
在“序列化”方面你应该这样做:
base64_encode(serialize($object));
在“反序列化”方面:
unserialize(base64_decode($object));
serialize
函数内部是如何工作的,你可以阅读
PHP 内部书籍:序列化:
上面的序列化字符串中的都是NUL字节。正如您所看到的,私有和受保护的成员使用相当特殊的名称进行序列化:私有属性以 ClassName 为前缀,受保护属性以 * 为前缀。这些名称是名称修改的结果,我们将在后面的部分中介绍这一点。
要直接回答问题,您可以像这样删除空字节:
$string = str_replace("\0", "", $string);
如果您存储序列化信息(不建议长期存储),那么将来使用较新的代码对其进行反序列化可能会导致问题,特别是如果您删除了空字符。您可以添加此方法来处理已删除或更新的属性:
/**
* @copyright 2024 Frank Forte
* @licence MIT
*/
public function __unserialize(array $data): void
{
$deprecated_props = ['removed_property'];
foreach ($data as $key => $value) {
// serialize function identifies protected/private member
// variables with the syntax null*null
if (substr($key,0,3) == "\0*\0") { // or $key[0] == '*' if nulls removed from serialized string
$key = substr($key, 3);
}
$prop = "\0" . static::class . "\0"; // without the "\0"s if nulls removed from serialized string
$len = strlen($prop);
if (substr($key,0,$len) == $prop) {
$key = substr($key, $len);
}
// Avoid "Creation of dynamic property MyClass::$prop is deprecated" error.
if (in_array($key, $deprecated_props)) {
continue;
}
$this->$key = $value;
}
}