【问题标题】:How to deserialize Perl Data::Dumper output in PHP如何在 PHP 中反序列化 Perl Data::Dumper 输出
【发布时间】:2012-09-03 09:05:52
【问题描述】:

我在 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 中反序列化这些数据?

附注我已经在 DB 中有这种格式的数据,我无法将其更改为 json 或其他格式。

【问题讨论】:

  • 我会将数据序列化为通用标准,例如 JSON,而不是您使用的任何格式(我猜是 Data::Dumper)。
  • 你确定你的意思是“序列化”而不是“反序列化”吗?
  • 以特定语言的序列化格式保存数据是一个糟糕的举动。经验教训:始终使用标准,即使您认为不需要它们。
  • Data::Dumper 并不是一个很好的序列化格式。

标签: php perl serialization data-dumper


【解决方案1】:
use JSON;

(或任何其他数据交换格式,如 XML)

JSON 文档和示例可在CPAN 获得

【讨论】:

    【解决方案2】:

    如果您可以更改 Perl 代码,请执行 as amon suggests 并使用一些标准的序列化格式,例如 JSONXMLYAML,您可以在 PHP 中反序列化。

    如果你真的愿意,你甚至可以make Perl output PHP's native serialization format,尽管我通常不建议这样做。 (如果你接下来想在 Python 中反序列化相同的数据呢?)

    如果您不能更改 Perl 代码,则只能硬着头皮尝试在 PHP 中解析 Data::Dumper 输出。我找不到任何现有的代码来做到这一点,所以看起来你可能必须自己编写。这可能是 parser generator 的工作,尽管格式(通常)很简单,您可能只需手动编码即可。


    编辑:既然你说你在数据库中有这个序列化的数据,为什么不写一个 Perl 程序来读取数据并将其转换为更标准的JSON之类的序列化格式?

    【讨论】:

      【解决方案3】:

      既然你说你不能改变格式:

      我不喜欢使用 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 字符串更新您的数据库行。这将使您在将来免于头疼,并允许您根据新标准更新所有数据。

      【讨论】:

      • 如果输入中的任何字符串包含花括号或字符串undef,这可能会产生令人惊讶的结果。 (对于后者,在eval 之前执行define('undef', null); 可能更容易、更安全。)
      • (另外,你真的必须在你的答案中包含原始字符串的副本和print_r 输出吗?如果你删除它们。)
      • 为了可读性截断了上面的内容。我喜欢你关于定义的观点,这是一个很好的建议。现在使用正则表达式来解决{} 会出现在字符串中的问题。
      • 您可以将它们替换为 "array(#{\n"")#}\n" 之类的内容,然后循环输出以撤消替换。 (通过在替换中包含{},编码实际上也应该是完全可逆的。)
      • 我在考虑这个,但为了简单和代码认知,我想避免第二次替换循环。
      【解决方案4】:

      由于它不是 JSON,但它看起来像 JSON,您可以尝试修改 JSON 库以使用该格式。我拿了这个JSON library,用=&gt; 替换了:,并添加了undef,如您所见here(第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] => 
      )
      

      这就是你要找的吗?

      【讨论】:

        【解决方案5】:

        您有很多建议尝试以一种或另一种方式解析它,但真正的问题是为什么?

        为什么不只用一个小的 Perl 程序来加载它,然后输出一个等效的 JSON 字符串。

        然后您可以在 PHP 中调用该 Perl 程序来进行转换;这意味着您正在使用 Perl 来读取 Perl 格式,这将保证正确的转换。

        或者(更好)对整个数据库批量运行它,以摆脱数据库中特定于 Perl 的数据格式;那么你就可以使用 PHP 的标准 JSON 函数了。

        这将使您的 PHP 代码(或您以后需要用来读取数据的任何其他语言)的生活变得如此简单。

        【讨论】:

        • 这是显而易见且唯一可靠的解决方案。
        • 也比使用 eval 更安全
        【解决方案6】:

        显而易见且唯一可靠的解决方案是使用 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);
        }
        

        【讨论】:

          猜你喜欢
          • 2011-06-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-09-29
          • 1970-01-01
          • 2016-06-11
          • 1970-01-01
          相关资源
          最近更新 更多