Как десериализовать данные 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 или другой.

Author: Ilmari Karonen, 2012-09-10

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 строка. Это избавит вас от головной боли в будущем и позволит обновить все ваши данные для нового стандарта.

 1
Author: Mike Mackintosh, 2012-09-10 14:02:08

У вас есть ряд предложений по попытке проанализировать его так или иначе, но реальный вопрос в том, почему?

Почему бы просто не создать небольшую программу на Perl, которая загружает ее и выдает эквивалентную строку JSON.

Затем вы можете либо вызвать эту программу Perl из вашего PHP, чтобы выполнить преобразование; это будет означать, что вы используете Perl для чтения формата Perl, что гарантирует правильное преобразование.

Или (еще лучше) запустите его для всей вашей базы данных в пакетный, чтобы избавиться от специфичного для Perl формата данных из БД; затем вы можете просто использовать стандартные функции JSON PHP.

Это значительно упростило бы жизнь в вашем PHP-коде (или на любом другом языке, с помощью которого вам нужно будет прочитать данные позже).

 5
Author: SDC, 2012-09-10 14:20:55

Поскольку это не 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] => 
)

Это то, что ты ищешь?

 3
Author: Alexei, 2012-09-10 14:08:03

Очевидным и единственным надежным решением является использование 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);
}
 3
Author: mob, 2012-09-10 14:35:28
use JSON;

(или любой другой формат обмена данными, например XML)

Документация и примеры JSON доступны по адресу CPAN

 1
Author: amon, 2012-09-10 13:39:19

Если вы можете изменить код Perl, то сделайте , как предлагает амон, и используйте какой-нибудь стандартный формат сериализации, такой как JSON или XML или YAML, который вы можете десериализовать в PHP.

Вы могли бы даже заставить Perl выводить собственный формат сериализации PHP, если бы вы действительно этого хотели, хотя я бы обычно не рекомендовал этого. (Как насчет того, когда вы в следующий раз захотите десериализовать те же данные, скажем, в Python?)

Если вы не можете изменить Код на Perl, вам просто придется стиснуть зубы и попытаться проанализировать вывод Data::Dumper в PHP. Я не смог найти никакого существующего кода для этого, так что, похоже, вам, возможно, придется написать свой собственный. Это может быть работа для генератора синтаксического анализа , хотя формат (обычно) достаточно прост, чтобы вы могли просто вручную его закодировать.


Редактировать: Поскольку вы говорите, что у вас есть эти сериализованные данные в базе данных, почему бы просто не написать программу на Perl, чтобы прочитать данные и преобразовать их в более стандартный формат сериализации, такой как JSON?

 1
Author: Ilmari Karonen, 2017-05-23 10:32:33