I was trying to tie an hash (or hashref) in order of tracking variable usages.
Everything is working for simple cases, but when I tried to use my module on some real code I had this error:
hash- or arrayref expected (not a simple scalar, use allow_nonref to allow this)
I've replicated the error using the following code:
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
The same code works with a plain hash.
I'd need this to work also in the second case, the code base is huge and I don't want to change it or live with the doubt that something somewhere will not work in some particular case.
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 version: v5.18.2
Minimal demonstration:
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 is a front-end for JSON::PP (default) or JSON::XS (if found). This is a problem with JSON::XS.
A lot of XS code doesn't handle magical variables (which is what $tied{EXPR}
returns), and while JSON::XS has handled magical values since version 1.2, it doesn't for the value directly passed to encode_json
.
This is an existing bug in JSON::XS that can be worked around as follows:
encode_json(my $non_magical = $tied{data})
Bug reported.
Unable to replicate using the code given, so what you're providing doesn't seem to be representative of your actual situation. The only thing I see that's the tiniest bit off is this line:
my @val = $tied_hash{key1};
in which you're assigning a scalar (your stored arrayref) to an array. Perl handles this fine, assembling an array with the scalar as sole content, but if your actual use case involves something more complex (maybe something with sub prototypes involved), conceivably something might be going wrong there.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With