我有一个数组
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
合并。
答案 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";
对于结果集上方的每个$row
,keys %$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模块是多余的。