Почему я получаю эту ошибку? - PullRequest
1 голос
/ 16 мая 2011

Это мой код

#!/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

Почему я получаю это?

Как это можно исправить?

Ответы [ 4 ]

7 голосов
/ 16 мая 2011
Объект

A JSON (по крайней мере, в версии XS, см. Ниже) является просто ссылкой SCALAR, поэтому вы не можете выполнить операцию с хеш-ссылкой. На практике большинство объектов Perl, с которыми вы столкнетесь, будут хеш-ссылками, но это не всегда так.

Я не уверен, чего вы пытаетесь достичь, используя JSON для кодирования объекта JSON. Вам нужно закодировать внутренности объекта JSON? Или вам просто нужно сериализовать данные пользователя и владельца? В последнем случае вам просто нужно использовать новую ссылку на хеш для хранения этих данных и передачи в JSON. Если вам действительно требуется кодировка объекта JSON, возможно, вам повезет больше, если использовать JSON::PP (вариант «Pure Perl» модуля JSON), который использует ссылку на хеш.

2 голосов
/ 16 мая 2011

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

2 голосов
/ 16 мая 2011

Потому что $ json в вашем случае - это сам кодировщик, который является ссылкой на SCALAR. Попробуйте использовать другую переменную для хранения вашего результата. Что-то вроде

my %json_result = (users => $json->encode(\%user_result),
                   owners => $json->encode(\%owner_result));
2 голосов
/ 16 мая 2011

Мне кажется, что $json = $json->utf8; заменяет хеш-ссылку $ json на скаляр, результат $ json-> utf8.

Перед строками, которые присваивают $ json -> {...}, используйте Dumper из модуля Data :: Dumper, чтобы увидеть, что в нем есть.

use Data::Dumper;
print Dumper($json);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...