如何将深度查询参数转换为Perl数据结构



我学习使用datatable在我的站点上绘制动态表,使用服务器端数据作为表的源。Datatables在查询中使用复杂的参数,我想将其转换为适当的Perl数据结构。因此,像这样的查询字符串(为了清晰起见,换行):

columns[0][data]=status&
columns[0][name]=&
columns[0][searchable]=true&
columns[0][orderable]=true&
columns[0][search][value]=&
columns[0][search][regex]=false&
columns[1][data]=some&
columns[1][name]=&
columns[1][searchable]=true&
columns[1][orderable]=true&
columns[1][search][value]=&
columns[1][search][regex]=false&
columns[2][data]=title&
columns[2][name]=&
columns[2][searchable]=true&
columns[2][orderable]=true&
columns[2][search][value]=&
columns[2][search][regex]=false

会变成:

@columns = ( {
    data => 'status',
    name => '',
    searchable => 1,
    orderable => 1,
    search => {
      value => '',
      regex => 0,
    }
  },
  {
    data => 'true',
    name => '',
    searchable => 1,
    orderable => 1,
    search => {
      value => '',
      regex => 0,
    }
  },
  {
    data => 'title',
    name => '',
    searchable => 1,
    orderable => 1,
    search => {
      value => '',
      regex => 0,
    }
  },
);

实现它的最好方法是什么?

编辑。此外,在本例中,我使用CGI.pm来检索查询参数,这为我提供了平面数据结构。

use Data::Diver 'DiveVal';
my @columns;
my %translate = ( 'true' => 1, 'false' => 0 );
for my $param ( $query->param() ) {
    if ( $param =~ /^columns/ ) {
        my $value = $query->param($param);
        DiveVal( @columns, $param =~ /[(.*?)]/g )
            = $translate{$value} // $value;
    }
}

假设您从CGI对象中提取了参数,那么以下操作可以工作:

use strict;
use warnings;
my %params = (
    'columns[0][data]'          => 'status',
    'columns[0][name]'          => '',
    'columns[0][searchable]'    => 'true',
    'columns[0][orderable]'     => 'true',
    'columns[0][search][value]' => '',
    'columns[0][search][regex]' => 'false',
    'columns[1][data]'          => 'some',
    'columns[1][name]'          => '',
    'columns[1][searchable]'    => 'true',
    'columns[1][orderable]'     => 'true',
    'columns[1][search][value]' => '',
    'columns[1][search][regex]' => 'false',
    'columns[2][data]'          => 'title',
    'columns[2][name]'          => '',
    'columns[2][searchable]'    => 'true',
    'columns[2][orderable]'     => 'true',
    'columns[2][search][value]' => '',
    'columns[2][search][regex]' => 'false',
);
my @columns;
while (my ($key, $val) = each %params) {
    next if $key !~ /^columns/;
    my @keys = $key =~ /[(.*?)]/g;
    my $ref = $columns[shift @keys] ||= {};
    $ref = $ref->{shift @keys} ||= {} while @keys > 1;
    $ref->{$keys[0]} = $val;
}
use Data::Dump;
dd @columns;

输出:

(
  {
    data => "status",
    name => "",
    orderable => "true",
    search => { regex => "false", value => "" },
    searchable => "true",
  },
  {
    data => "some",
    name => "",
    orderable => "true",
    search => { regex => "false", value => "" },
    searchable => "true",
  },
  {
    data => "title",
    name => "",
    orderable => "true",
    search => { regex => "false", value => "" },
    searchable => "true",
  },
)

您可以尝试这样做:

#! /usr/bin/perl
use warnings;
use strict;
my $qs="columns[0][data]=status&columns[0][name]=&columns[0][searchable]=true&columns[0][orderable]=true&columns[0][search][value]=&columns[0][search][regex]=false&columns[1][data]=some&columns[1][name]=&columns[1][searchable]=true&columns[1][orderable]=true&columns[1][search][value]=&columns[1][search][regex]=false&columns[2][data]=title&columns[2][name]=&columns[2][searchable]=true&columns[2][orderable]=true&columns[2][search][value]=&columns[2][search][regex]=false";
my @data=split ("&",$qs);
my @col;
for (@data) {
   my ($val)=/=(.*)$/;
   $_=~s/=.*//;
   my @b=split(/[(.*?)]/);
   my @c=@b[grep {$_% 2} 0..$#b];
   if (@c==2) {
      $col[$c[0]]->{$c[1]}=$val;
   } else {
      $col[$c[0]]->{$c[1]}{$c[2]}=$val;
   }
}

或使用eval作为更一般的解决方案:

for (@data) {
   my ($val)=/=(.*)$/;
   $_=~s/=.*//;
   my @b=split(/[(.*?)]/);
   my @c=@b[grep {$_% 2} 0..$#b];
   my $cmd='$col[$c[0]]->';
   for my $i (1..$#c) {
      $cmd.='{$c['.$i.']}';
   }
   $cmd.='=$val';
   eval ($cmd);
}

最新更新