Почему я получаю эту ошибку?

#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, потому что нет необходимости присваивать хэшу, который будет кодироваться, имя. Мы используем его только один раз.