Bagaimana cara mengubah parameter kueri mendalam menjadi struktur data Perl?

Saya belajar menggunakan Datatables untuk menggambar tabel dinamis di situs saya, menggunakan data sisi server sebagai sumber tabel. Datatables menggunakan parameter rumit dalam kueri, yang ingin saya ubah menjadi struktur data Perl yang tepat. Jadi, string kueri seperti ini (dibungkus menjadi beberapa baris untuk kejelasan):

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

akan menjadi seperti:

@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,
    }
  },
);

Apa cara terbaik untuk mencapainya?

Sunting. Selain itu, dalam kasus khusus ini saya menggunakan CGI.pm untuk mengambil kembali parameter kueri, ini memberi saya struktur data yang datar.


person w.k    schedule 01.06.2014    source sumber
comment
Sudah ada integrasi Perl untuk tabel data yang dapat memberikan apa yang Anda butuhkan datatables.net/development/server- samping/Perl_mvc   -  person KeepCalmAndCarryOn    schedule 02.06.2014
comment
@KeepCalmAndCarryOn: AFAIU, ini dan Perl Module Datatables tidak kompatibel dengan API baru Datatables.   -  person w.k    schedule 02.06.2014


Jawaban (3)


Dengan asumsi Anda menarik params dari objek CGI, maka yang berikut ini bisa berfungsi:

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;

Keluaran:

(
  {
    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",
  },
)
person Miller    schedule 01.06.2014

Anda dapat mencoba sesuatu seperti:

#! /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;
   }
}

atau menggunakan eval untuk solusi yang lebih umum:

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);
}
person Håkon Hægland    schedule 01.06.2014

person    schedule
comment
Konstruksi apa ini, tempat Anda menetapkan pemanggilan fungsi (DiveVal() = ...)? - person w.k; 02.06.2014
comment
@w.k: ini adalah fitur yang sedikit digunakan yang disebut lvalue subs; kapal selam harus menyatakan bahwa ia boleh dipanggil seperti itu. ini sangat berguna dalam kasus seperti ini ketika sub membuat wadah baru yang mungkin akan ditugaskan padanya. Ada DiveRef alternatif yang tidak istimewa yang Anda sebut seperti ${ DiveRef( ... ) } = $value - person ysth; 02.06.2014