这是我的代码
#!/usr/bin/perl -T
use CGI;
use CGI::Carp qw(fatalsToBrowser);
use CGI qw(:standard);
use JSON;
use utf8;
use strict;
use warnings;
# ... ;
my $cgi = CGI->new;
$cgi->charset('UTF-8');
my @owners = map { s/\s*//g; $_ } split ",", $cgi->param('owner');
my @users = map { s/\s*//g; $_ } split ",", $cgi->param('users');
my $json = JSON->new;
$json = $json->utf8;
my %user_result = ();
foreach my $u (@users) {
$user_result{$u} = $db1->{$u}{displayName};
}
my %owner_result = ();
foreach my $o (@owners) {
$owner_result{$o} = $db2{$o};
}
$json->{"users"} = $json->encode(\%user_result);
$json->{"owners"} = $json->encode(\%owner_result);
$json_string = to_json($json);
print $cgi->header(-type => "application/json", -charset => "utf-8");
print $json_string;
和这些行
$json->{"users"} = $json->encode(\%user_result);
$json->{"owners"} = $json->encode(\%owner_result);
给出错误
Not a HASH reference
为什么我会这样做?
如何修复?
答案 0 :(得分:7)
JSON
对象(至少在XS版本中,见下文)只是一个SCALAR引用,因此您无法对其执行哈希引用操作。实际上,您遇到的大多数Perl对象都是哈希引用,但情况并非总是如此。
我不确定您要通过使用JSON对JSON对象进行编码来实现目标。您需要编码JSON对象的内部吗?或者您只需要序列化用户和所有者数据?在后一种情况下,您应该使用新的哈希引用来保存该数据并传递给JSON。如果你确实需要对JSON对象进行编码,那么使用JSON::PP
(JSON模块的“Pure Perl”变体)可能会有更好的运气,它使用哈希引用。
答案 1 :(得分:2)
在我看来$json = $json->utf8;
正在用标量取代$ json hash ref,结果是$ json-> utf8。
在分配给$ json-> {...}的行之前,使用Data :: Dumper模块中的Dumper来查看其中的内容。
use Data::Dumper; print Dumper($json);
答案 2 :(得分:2)
因为你的案例中的$ json是编码器本身,它是对SCALAR的引用。尝试使用不同的变量来保存结果。像
这样的东西my %json_result = (users => $json->encode(\%user_result),
owners => $json->encode(\%owner_result));
答案 3 :(得分:2)
你的大问题是$json
是JSON编码器对象,而不是要编码的数据结构。你应该建立一个单独的数据结构。
您的另一个问题是您正在尝试对JSON进行双重编码。这段代码:
my $data; # I've added this to fix your first bug
$data->{"users"} = $json->encode(\%user_result);
$data->{"owners"} = $json->encode(\%owner_result);
$json_string = to_json($data);
会创建一个JSON字符串,在解码时会给你一个带有两个键的哈希值。每个键的值将是包含JSON编码的哈希的字符串。将每个值作为哈希更有意义。
所以,试试这个:
my $json_string = $json->encode({
users => \%user_result,
owners => \%owner_result,
});
这里,我使用匿名hashref,因为没有必要给哈希编码一个名字。我们只使用过一次。