#perl #json
#perl #json
Вопрос:
Это мой код
#!/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
Почему я это получаю?
Как это можно исправить?
Ответ №1:
JSON
Объект (по крайней мере, в версии XS, см. Ниже) — это просто СКАЛЯРНАЯ ссылка, поэтому вы не можете выполнить операцию хэширования ссылки на него. На практике большинство объектов Perl, с которыми вы сталкиваетесь, будут хэш-ссылками, но это не всегда будет так.
Я не уверен, чего вы пытаетесь достичь, используя JSON для кодирования объекта JSON. Вам нужно закодировать внутренние компоненты объекта JSON? Или вам просто нужно сериализовать данные пользователя и владельца? В последнем случае вам следует просто использовать новую ссылку на хэш для хранения этих данных и передачи в JSON. Если вам действительно требуется кодировка объекта JSON, возможно, вам повезет больше, используя JSON::PP
(вариант модуля JSON на «чистом Perl»), который использует ссылку на хэш.
Комментарии:
1. «вы должны просто использовать новую ссылку на хэш для хранения этих данных и передачи в JSON». Это именно то, что я пытаюсь сделать. =) Как мне это сделать?
2.
my $data; n $data->{users} = $json->encode(%user_result); n $data->{owners} = $json->encode(%owner_result); n $json_string = to_json($data);
, для одного способа
Ответ №2:
Мне кажется, что $json = $json->utf8;
это замена хэш-ссылки $ json на скаляр, результат $ json-> utf8.
Перед строками, которые присваивают значение $json->{…}, используйте Dumper из модуля Data::Dumper, чтобы посмотреть, что в нем.
используйте Data::Dumper; печатающий дамп ($ json);
Комментарии:
1. Тогда я получу
$VAR1 = undef;
также, если удалю строку utf-8.2. @Sandra Schlichting: Я думаю, вы делаете это в неправильном месте; поставьте
print Dumper($json);
непосредственно перед$json->{"users"} = $json->encode(%user_result);
Ответ №3:
Потому что $ json в вашем случае — это сам encoder, который является ссылкой на SCALAR. Попробуйте использовать другую переменную для хранения вашего результата. Что-то вроде
my %json_result = (users => $json->encode(%user_result),
owners => $json->encode(%owner_result));
Ответ №4:
Ваша большая проблема в том, что $json
это объект JSON encoder, а не структура данных, которая должна быть закодирована. Вы должны создавать отдельную структуру данных.
Ваша другая проблема заключается в том, что вы пытаетесь дважды закодировать свой 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, потому что нет необходимости присваивать хэшу, который будет кодироваться, имя. Мы используем его только один раз.