带着所有的仇恨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/