perl - 无法弄清楚为什么 Seral 编码器/解码器往返没有返回正确的对象

标签 perl object-persistence

带着所有的仇恨Storable -- 我决定查看 Sereal以满足序列化的需要。另外,我在 Storable 方面遇到了一些 32 位/64 位跨平台问题,所以我认为这将是一个好时机。

遇到一些问题后,我将问题归结为以下代码。 (我正在保留一个 HTTP::Request 对象,因此是示例代码)。

这是我的编码测试,我正在存储到文件中:

use Sereal::Encoder;
use HTTP::Request;
use HTTP::Headers;
use URI;

my $encoder = Sereal::Encoder->new();

open(my $fh, ">", 'myfile.data') or die $!;
binmode($fh);
my $uri = URI->new('http://www.example.com');
my $headers = HTTP::Headers->new(
    Content_Type => 'application/json',
);
my $http_request = HTTP::Request->new(POST => $uri, $headers, 'bleh');
print $fh $encoder->encode( $http_request );
close($fh);

在同一台机器上(5.18 上的相同 perl 等),我运行以下命令:

use Sereal::Decoder;
use File::Slurp qw(read_file);
use URI;

my $data = read_file('myfile.data') or die $!;
my $dec = Sereal::Decoder->new();
my $decoded = $dec->decode($data);
print $decoded->{_uri}->scheme,"\n";

运行编码程序,然后运行解码程序的输出是:

无法通过 testd.pl 第 8 行的包“URI::http”找到对象方法“scheme”。

无论如何,真的很困扰我问题出在哪里。我最终恢复到 Storable 并使用 nfreeze 来解决 Storable 的架构问题,但想知道为什么我尝试转换到 Sereal 崩溃并烧毁。

谢谢!

最佳答案

Sereal 与 Storable 不同,当遇到序列化对象时不会自动加载模块。这是 Storable 的安全问题,因此 Sereal 正在按预期工作。 [1]

在第二个测试程序中调用 scheme 时,URI::http 尚未加载,因此方法调用会导致错误。当 URI 的构造函数用于“看起来像”其中之一的字符串时,URI 似乎会加载其子类,例如

URI->new('http://www.stackoverflow.com');

加载 URI::http 模块。因此,一种解决方案是添加该构造函数的虚拟调用以确保加载 URI::http,或者手动使用 URI::http。任一选项都会导致第二个脚本的 print $decoded->{_uri}->scheme 行按预期工作,但我认为第二个是两害相权取其轻(从 URI 导入未记录的子模块)与专门针对其不立即明显的副作用而进行的任意方法调用相比)。

关于perl - 无法弄清楚为什么 Seral 编码器/解码器往返没有返回正确的对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25860547/

相关文章:

android - 我如何在 ORMLite 中将 "map"作为所有数据库实体扩展的基础对象

php - 在领域驱动设计中,存储库模式是否维护对对象的引用?

perl - Digest::SHA 相对于 Digest::SHA1 有哪些优点?

perl - POP3 是否区分已读和未读邮件

grails - 我是否需要在 grails 中显式刷新 GORM 保存调用?

delphi - Delphi 的运行时可更改 ORM/OPF 对象持久性框架

.net 对象持久性

perl - 有没有办法在运行时获取当前(当前未执行)文件的目录?

perl - 如何调试单个 Perl 单元测试子?

regex - Perl:从字符串中提取多个数字