我需要在Perl中序列化PHP格式



我可以使用PHP:: serialization用PHP序列化格式序列化哈希值.

$result = serialize({ a => 1111, b => 2222})
# IT GIVES ME 'a:2:{s:1:"a";i:1111;s:1:"b";i:2222;}';

但是当值是字符串时,我需要将它们视为字符串,即使它们看起来像数字或日期。

$result = serialize({ a => '1111', b => '2222'});
# IT GIVES ME THE SAME 'a:2:{s:1:"a";i:1111;s:1:"b";i:2222;}';

这就是我需要的:

# 'a:2:{s:1:"a";s:4:"1111";s:1:"b";s:4:"2222";}'

好吧,Perl是非常松散的类型,但如果我说什么是字符串…它不应该被视为字符串吗?

PHP:序列化可以选择将双精度或浮点数视为字符串,但将整数、日期等视为字符串,即使加上引号也可以恢复其Perl类型。我尝试了双引号和单引号,还有q(), qq(), qw(),但没有运气。甚至像"1111" . ""这样的把戏。

我在CPAN中找不到替代方案。我需要重写PHP::Serialization吗?

您不需要编写自己的解析器。你可以继承PHP::Serialization。或者至少你可以试试。

我下面的实现可以用作您示例中的插入,但它有限制。

模块看起来像它允许子类化,因为serializedeserialize函数使用__PACKAGE__实例化,new也使用$class。但仔细观察就会发现,文件作用域中有几个词法变量基本上是与子类隔离的。因此,失去了一些功能。您也不能继承像@EXPORT_OK这样的包变量,并且通常出口商不能很好地处理OO代码。

我的代码可以用作您的特定示例的插入替代,我相信它可以序列化数据结构,只要它们没有排序。如果需要$sorthash(即encode$shash参数),则会遇到麻烦,因为子类中的词法变量与父类中的词法变量不同,并且没有相同的方法可以获得它。

为了使它工作,我们必须重新定义serialize并导出它。

我做了一个非常天真的hack,把所有不是数据结构或对象的东西都当作字符串,基本上消除了数字。

package PHP::Serialization::MoreStringent;
use strict;
use warnings;
use Scalar::Util qw/blessed/;
use Carp qw(confess);
use parent 'PHP::Serialization';
# we need this so the non-OO functions can be exported
our @EXPORT_OK = qw(serialize);
sub serialize   { __PACKAGE__->new->encode(@_) }
# this thing is bad, because it's now lexical in our subclass - so it breaks
my $sorthash;
# this is mostly a copy of the original code
sub encode {
my ($self, $val, $iskey, $shash) = @_;
$iskey=0 unless defined $iskey;
$sorthash=$shash if defined $shash;
if ( ! defined $val ) {
return $self->_encode('null', $val);
}
elsif ( blessed $val ) {
return $self->_encode('obj', $val);
}
elsif ( ! ref($val) ) {
# very naive hack to make all other things into string
return $self->_encode('string', $val);
}
else {
my $type = ref($val);
if ($type eq 'HASH' || $type eq 'ARRAY' ) {
return $self->_sort_hash_encode($val) if (($sorthash) and ($type eq 'HASH'));
return $self->_encode('array', $val);
}
else {
confess "I can't serialize data of type '$type'!";
}
}
}
1;
现在我们可以用下面的测试来运行它,它至少会产生您想要的输出。
use Test::More;
use PHP::Serialization::MoreStringent 'serialize';
is serialize({ a => 1111, b => 2222}), 'a:2:{s:1:"a";s:4:"1111";s:1:"b";s:4:"2222";}';
done_testing;

我没有用数据结构测试它,因为我不知道它们在PHP的序列化格式中应该是什么样子。我故意删除了反序列化,因为这会大量使用$sorthash变量,所以我们基本上已经破坏了它。我想。

但是概念应该清楚。


作为替代方案,您是否可以对输出进行后处理并对引号进行正则化?

最新更新