Как десериализовать данные Perl::Вывод дампера в PHP
У меня есть результат переменной экспорта в 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. У меня уже есть данные в этом формате в БД, я не могу изменить их на json или другой.
6 answers
Поскольку вы заявили, что не можете изменить формат:
Мне не нравится использовать eval, но поскольку ваш синтаксис настолько близок к ожидаемому синтаксису массива PHP, я думаю, что мы можем оставить это без внимания.
Установите $string
равным содержимому из вашей базы данных, которое соответствует приведенному ниже формату. Ниже приведен рабочий пример использования предоставленных вами данных. В конце дня PHP установит переменную в начале вашей переменной perl в новый анализируемый массив.
Так как это происходит чтобы быть текстовым блоком/большой строкой, выполните:
<?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 строка. Это избавит вас от головной боли в будущем и позволит обновить все ваши данные для нового стандарта.
У вас есть ряд предложений по попытке проанализировать его так или иначе, но реальный вопрос в том, почему?
Почему бы просто не создать небольшую программу на Perl, которая загружает ее и выдает эквивалентную строку JSON.
Затем вы можете либо вызвать эту программу Perl из вашего PHP, чтобы выполнить преобразование; это будет означать, что вы используете Perl для чтения формата Perl, что гарантирует правильное преобразование.
Или (еще лучше) запустите его для всей вашей базы данных в пакетный, чтобы избавиться от специфичного для Perl формата данных из БД; затем вы можете просто использовать стандартные функции JSON PHP.
Это значительно упростило бы жизнь в вашем PHP-коде (или на любом другом языке, с помощью которого вам нужно будет прочитать данные позже).
Поскольку это не 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] =>
)
Это то, что ты ищешь?
Очевидным и единственным надежным решением является использование 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);
}
use JSON;
(или любой другой формат обмена данными, например XML)
Документация и примеры JSON доступны по адресу CPAN
Если вы можете изменить код Perl, то сделайте , как предлагает амон, и используйте какой-нибудь стандартный формат сериализации, такой как JSON или XML или YAML, который вы можете десериализовать в PHP.
Вы могли бы даже заставить Perl выводить собственный формат сериализации PHP, если бы вы действительно этого хотели, хотя я бы обычно не рекомендовал этого. (Как насчет того, когда вы в следующий раз захотите десериализовать те же данные, скажем, в Python?)
Если вы не можете изменить Код на Perl, вам просто придется стиснуть зубы и попытаться проанализировать вывод Data::Dumper в PHP. Я не смог найти никакого существующего кода для этого, так что, похоже, вам, возможно, придется написать свой собственный. Это может быть работа для генератора синтаксического анализа , хотя формат (обычно) достаточно прост, чтобы вы могли просто вручную его закодировать.
Редактировать: Поскольку вы говорите, что у вас есть эти сериализованные данные в базе данных, почему бы просто не написать программу на Perl, чтобы прочитать данные и преобразовать их в более стандартный формат сериализации, такой как JSON?