从DBI获取JSON:Pg selectall_arrayref

时间:2013-12-20 02:24:59

标签: json perl map dbi

我有一个数组

my @cols = ("accountid", "balance");

和数据集

my $rowsref=$dbh->selectall_arrayref($_[0]);
foreach my $row (@$rowsref) {
    print join(", ", map {defined $_ ? $_ : "(null)"} @$row), "\n";
}

打印"1, 150"

我想获得像[{"accountid": 1, "balance": 150},{..}]这样的JSON输出。

我已加载JSON模块,但不确定如何将@cols与每个$row合并。

2 个答案:

答案 0 :(得分:2)

编辑:在第二个例子中添加了列名交易的说明
编辑:修复了您对整个结果集的单个JSON编码的要求 编辑:在第二个示例中的cols映射代码中忘记了keys 编辑:错误的hashref到处都是arrayref。 : -

首先,请改用selectall_hashref,以便它已包含密钥名称。 然后使用其中一个JSON编码模块对每一行进行编码。

(与您的代码做出相同的假设......)

按原样使用selectall_hashref()中的list-of-hashref:

use JSON::XS;
use 5.10.0;
my $rowsref = $dbh->selectall_hashref($_[0]);
print JSON::XS::encode_json($rowsref),"\n";

对selectall_hashref()的colnames进行翻译:

如果数据库中的列名与列名不同,那么您需要一个映射:

use JSON::XS;
use 5.10.0;
my $trans = { account => 'accountid', amount => 'balance' };
my $rowsref = $dbh->selectall_hashref($_[0]);
my $output = [];
for my $row (@$rowsref) {
    push @$output, {
        map { 
            my $colname = exists($trans->{$_}) ? $trans->{$_} : $_;
            my $value   = $row->{$_};
            $colname => $value;
        } keys %$row                   
    });
}
print JSON::XS::encode_json($output),"\n";

对于结果集上方的每个$rowkeys %$row会返回从数据库返回的行中的列名。

map操作获取每个列名并产生2个标量值; (1)$colname或者是原始数据库列名,或者(如果它在$trans hashref中找到)是列名的“转换”; (2)$value是数据库在此特定$row中为此列名返回的值。 $colname => $value会将地图中的$colname$value作为“展平”的标量值对返回。这意味着map操作返回的标量值列表的长度是keys %$row返回的原始列名列表的两倍。

最后,push @$output, { ... }key,value,key,value,...顺序从标量值列表中创建匿名哈希引用,并将其添加到$ output数组引用的末尾。

selectall_arrayref()

的盲目翻译

如果(出于某种原因)你对从数据库中查询hashrefs有一种病态厌恶,我想你可以这样做:

use 5.10.0;    
my @cols = ("accountid", "balance");
my $rowsref = $dbh->selectall_arrayref($_[0]);
my $output = [];
for my $row (@$rowsref) {
    my %row = map { $cols[$_] => $row->[$_] } (0 .. $#cols);
    push @$output, \%row; 
}
print JSON::XS::encode_json($output),"\n";

这假设从查询中只有两列回来。

“已定义或”运营商:

顺便说一句......假设perl足够晚,你可以替换这类东西:

defined $_ ? $_ : "(null)"

用这个:

$_ // "(null)"

如果你的代码编辑器(例如:Vim)与perl不是最新的,它可能无法正确地突出显示它。 (例如:它可能将其视为m//构造)。

答案 1 :(得分:0)

请注意,PostgreSQL也可以生成JSON。如果它是您的选项,则Perl JSON模块是多余的。