【问题标题】:Strange behavior of a tied hash in perl, when asking for an arrayrefperl 中绑定哈希的奇怪行为,当请求一个 arrayref 时
【发布时间】:2015-11-16 15:26:23
【问题描述】:

我试图按照跟踪变量使用的顺序绑定一个哈希(或 hashref)。

一切都适用于简单的情况,但是当我尝试在一些真实代码上使用我的模块时,我遇到了这个错误:

hash- or arrayref expected (not a simple scalar, use allow_nonref to allow this)

我已经使用以下代码复制了错误:

use Tie::Hash::Usages;
use JSON;

my @arr = (
    {
        key1 => "ac",
        key2 => 12,
        key3 => 12
    },        
);
my %tied_hash;


tie %tied_hash, 'Tie::Hash::Usages';

$tied_hash{key1} = \@arr;

my @val = $tied_hash{key1};
print encode_json(\@val)."\n\n"; #this works

print encode_json($tied_hash{key1}); #this doesn't

相同的代码适用于普通哈希。

我需要它在第二种情况下也能工作,代码库很大,我不想改变它,也不想怀疑某处某处在某些特定情况下无法工作。

Usages.pm(简体)

package Tie::Hash::Usages;
use strict;
use warnings;

use Tie::Hash;

use vars qw(@ISA);

@ISA = qw(Tie::StdHash);

sub TIEHASH {

    my ($class, $tracker, $filename) = @_;
    my %hash;

    bless \%hash, $class;

}

sub STORE {
    my ($self, $key, $val) = @_;
    $self->{$key} = $val;
}

sub DELETE {
    my ($self, $key) = @_;
    delete $self->{$key};

}

sub FETCH {
    my ($self, $key) = @_;
    return $self->{$key};
}

sub DESTROY {
    my $self = shift;
}
1;

perl 版本:v5.18.2

【问题讨论】:

  • 它对我有用。我在尝试 encode_json(@val) 时遇到错误。
  • 真的吗?是的,在这种情况下你会得到错误,因为 encode_json 需要一个 arrayref 作为输入。你用的是什么版本的perl?我在 v5.18.2
  • 在 5.8.3 和 5.22.0 中为我工作。

标签: perl tie


【解决方案1】:

最小演示:

use JSON::XS  qw( encode_json );
use Tie::Hash qw( );

our @ISA = 'Tie::StdHash';

{
   tie my %tied, __PACKAGE__;
   $tied{data} = { a => 1 };
   encode_json($tied{data});  # Exception: hash- or arrayref expected ...
}

JSON 是 JSON::PP(默认)或 JSON::XS(如果找到)的前端。这是 JSON::XS 的问题。

很多 XS 代码不处理魔法变量(这是 $tied{EXPR} 返回的),虽然 JSON::XS 从 1.2 版开始处理魔法值,但它不处理直接传递给 @987654324 的值@。

这是 JSON::XS 中的一个现有错误,可以通过以下方式解决:

encode_json(my $non_magical = $tied{data})

错误reported

【讨论】:

    【解决方案2】:

    无法使用给定的代码进行复制,因此您提供的内容似乎不能代表您的实际情况。我看到的唯一一点点就是这一行:

    my @val = $tied_hash{key1};
    

    您将标量(您存储的arrayref)分配给数组。 Perl 可以很好地处理这个问题,将标量作为唯一内容组装一个数组,但是如果您的实际用例涉及更复杂的事情(可能涉及子原型的事情),可以想象那里可能会出现问题。

    【讨论】:

    • 再次尝试将所有内容放入file。但是错误仍然发生在我身上。奇怪!
    • @chaos 如果您没有安装 JSON::XS,JSON.pm 将使用 JSON::PP 代替,它使用纯 perl 代码并且可以解决该问题。
    【解决方案3】:

    以太做对了。 JSON 库默认使用 JSON:XS(这会产生此问题)。我所要做的就是卸载 JSON::XS 并安装 JSON::PP

    1. sudo cpan
    2. 安装 cpan App::cpanminus
    3. 退出
    4. sudo cpanm --uninstall JSON::XS
    5. sudo cpan
    6. 安装 JSON::PP
    7. 退出

    希望这对某人有所帮助。

    【讨论】:

      猜你喜欢
      • 2017-07-29
      • 2013-03-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-15
      • 1970-01-01
      • 2019-09-09
      相关资源
      最近更新 更多