我在Perl中有一个导出变量的结果,如下字符串:
$VAR1 = {
'guard' => undef,
'work_hand' => undef,
'images' =>
{'1' =>
{
'mini_height' => 150,
'width' => 150,
'extension' => 'jpg',
'filename' => 'object_1.1330907414.96873.jpg',
'mini_width' => 150,
'class' => 'Ontico::Image',
'height' => 150,
'mini_filename' => 'object_1.1330907414.96873.mini.jpg',
'size' => 26053,
'symname' => 'big_logo'
},
'2' =>
{
'width' => 48,
'extension' => 'jpg',
'alt' => 'Даниэле Галлоппа',
'height' => 48,
'mini_filename' => 'object_91.1235312905.mini.jpg',
'size' => 12809,
'symname' => 'logo',
'mini_height' => 150,
'filename' => 'object_91.1235312905.jpg',
'mini_width' => 150,
'class' => 'Ontico::Image'
}
},
'show_league_banner' => 0,
'back_hand' => undef,
'weight_category' => undef,
'stick_position' => undef
};
如何在PHP中反序列化这些数据?
p.S.我在DB中已经有了这种格式的数据,我无法将其更改为json或其他格式
您有很多建议可以尝试以某种方式解析它,但真正的问题是为什么?
为什么不让一个小的Perl程序来加载它,并输出一个等效的JSON字符串呢。
然后,您可以从PHP中调用该Perl程序来进行转换;这意味着您正在使用Perl读取Perl格式,这将保证正确的转换。
或者(更好的是)在整个数据库中批量运行它,以摆脱数据库中Perl特定的数据格式;然后您就可以使用PHP的标准JSON函数了。
这样一来,PHP代码(或以后需要读取数据的任何其他语言)的生活就会简单得多。
显而易见且唯一稳健的解决方案是使用Perl将输入反序列化并保留为标准格式。能够完成这项任务的Perl程序也不需要很大。
// receive input in Perl's Data::Dumper format and produce PHP object output
function perl_dd_to_php( $dd_output ) {
$process = proc_open( "perl -000 -MJSON -e 'print encode_json eval <>'",
array( array("pipe","r"), array("pipe","w") ),
$pipes );
fwrite($pipes[0], $dd_output );
fclose($pipes[0]);
$json_string = stream_get_contents($pipes[1]);
fclose($pipes[1]);
return json_decode($json_string);
}
由于它不是JSON,但看起来像JSON,因此可以尝试修改JSON库以使用该格式。我使用了这个JSON库,用=>
替换了:
,并添加了undef
,如您所见(第496、671和681行)。这真的很简单,我想你可以用类似的方式解决其他差异。
结果是:
stdClass Object
(
[guard] =>
[work_hand] =>
[images] => stdClass Object
(
[1] => stdClass Object
(
[mini_height] => 150
[width] => 150
[extension] => jpg
[filename] => object_1.1330907414.96873.jpg
[mini_width] => 150
[class] => Ontico::Image
[height] => 150
[mini_filename] => object_1.1330907414.96873.mini.jpg
[size] => 26053
[symname] => big_logo
)
[2] => stdClass Object
(
[width] => 48
[extension] => jpg
[alt] => Даниэле Галлоппа
[height] => 48
[mini_filename] => object_91.1235312905.mini.jpg
[size] => 12809
[symname] => logo
[mini_height] => 150
[filename] => object_91.1235312905.jpg
[mini_width] => 150
[class] => Ontico::Image
)
)
[show_league_banner] => 0
[back_hand] =>
[weight_category] =>
[stick_position] =>
)
这就是你要找的吗?
use JSON;
(或任何其他数据交换格式,如XML)
JSON文档和示例可在CPAN 上获得
如果你可以更改Perl代码,那么按照amon的建议,使用一些标准的序列化格式,比如JSON、XML或YAML,你可以在PHP中反序列化。
如果你真的想的话,你甚至可以让Perl输出PHP的原生序列化格式,尽管我通常不建议这样做。(下次你想在Python中反序列化相同的数据时呢?)
如果不能更改Perl代码,那么您只需要咬紧牙关,尝试用PHP解析Data::Dumper输出。我找不到任何现有的代码来做这件事,所以看起来你可能必须自己写。这可能是解析器生成器的工作,尽管格式(通常)足够简单,您可能只需要手工编写代码
编辑:既然你说你在数据库中有这个序列化的数据,为什么不写一个Perl程序来读取数据并将其转换为更标准的序列化格式(如JSON)呢?
由于您声明不能更改格式:
我不喜欢使用eval,但因为您的语法是,所以接近预期的PHP数组语法,我认为我们可以顺其自然。
将$string
设置为数据库中符合以下格式的内容。请参阅下面的使用您提供的数据的工作示例。在一天结束时,PHP会将perl-var开头的变量设置为新解析的数组。
由于它将是一个文本块/大字符串,请执行:
<?php
$string = "'$VAR1 = {
'guard' => undef,
'work_hand' => undef,
'images' =>
{'1' =>
{
'mini_height' => 150,
... // truncated for readability
};";
$res = str_replace(array("{", "}", 'undef'), array("array(", ")", "''"), $string);
eval($res);
print_r($VAR1);
您的结果是:
Array
(
[guard] =>
[work_hand] =>
[images] => Array
(
[1] => Array
(
[mini_height] => 150 ...
注意:我建议您现在花点时间将数据库内容改装并升级为更标准的格式,只是为了将来更容易维护。
您可以在数据库中循环,逐行获取所有内容,然后将数据运行到上面的函数中,并将其封装在json_encode()
中,然后使用新的JSON字符串更新数据库行。这将在将来为您省去一个头痛的问题,并允许您为新标准更新所有数据。