如何解析由Perl中的jQuery.ajax()生成的复杂查询字符串?

时间:2017-03-01 17:47:28

标签: perl parsing cgi query-string

jQuery.ajax()将复杂的JavaScript对象编码为查询字符串,如下所示:

?a[b][]=1&a[b][]=2&a[c]=3

我想将其解码为Perl数据结构,如下所示:

{ a=>{ b=>[1,2], c=>3 } }

PHP默认执行此操作。有没有办法在Perl CGI脚本中执行此操作?不一定使用CGI.pm;我可以安装我想要的任何库。

到目前为止,我只能解码一维数组,因为CGI模块的param()函数可以返回一个数组。

2 个答案:

答案 0 :(得分:4)

您是否考虑过以JSON格式提交数据?这只是一个替换

的问题
data: data

data: JSON.stringify(data)

您甚至可以切换到POST以避免URI编码,URI解码和查询大小限制(尽管POST语义与GET语义不同)。

method:      "POST",
contentType: "application/json; charset=UTF-8",
data:        JSON.stringify(data)

无论如何,以下应该可以解决问题:

use Data::Diver qw( DiveVal );
use List::Util  qw( pairs );  # 1.29+
use URI         qw( );

my $url = URI->new('?a[b][]=1&a[b][]=2&a[c]=3', 'http');

my %data;
PAIR: for ( pairs( $url->query_form() ) ) {
   my ($k, $v) = @$_;

   my ( @k, $push );
   for (my $k_ = $k) {  # Basically C<< my $_ = $k; >>
      s/^(\w+)//
         or warn("Can't handle key $k\n"), next PAIR;

      push @k, $1;
      push @k, $1 while s/^\[(\w+)\]//;
      $push = s/^\[\]//;

      $_ eq ""
         or warn("Can't handle key $k\n"), next PAIR;
   }

   if ($push) {
      push @{ DiveVal(\%data, @k) }, $v;
   } else {
      DiveVal(\%data, @k) = $v;
   }
}

早于5.16的Perl版本需要一种解决方法。取代

use Data::Diver qw( DiveVal );
push @{ DiveVal(\%data, @k) }, $v;

use Data::Diver qw( DiveRef DiveVal );
push @{ ${ DiveRef(\%data, @k) } }, $v;

请注意,格式不明确 [1] 。例如,以下两个表达式产生相同的结果(a[0][x]=3 [2] ):

jQuery.param( { a: [      { x: 3 } ] } )

jQuery.param( { a: { "0": { x: 3 } } } )

我的代码将重现前者。数字键始终被视为数组索引。

  1. 使用JSON的另一个原因。
  2. 为了便于阅读,删除了一些转义。

答案 1 :(得分:1)

PHP解释像foo[]=123&foo[]=234&foo[]=345这样的查询字符串与所有Perl Web框架不同。我曾经为Mojolicious构建了一个PHP插件,并且必须解决很多这些差异。您可以找到这些差异的摘要和一些工作代码(最多可用于2级哈希),将Perl参数转换为PHP风格的参数here。也许你可以根据你的用例调整它。