eval of Data::Dumper output not same as original data structure

H

himanshu.garg

Why aren't the outputs of the two print statements same. I want
to reconstruct %hash1 into %hash2.

========================================
use strict;
use Data::Dumper;

my %hash1 = (key1 => 'value1', 'key2' => 'value2');

my %hash2 = eval Dumper(%hash1);

print Dumper(%hash1);

print Dumper(%hash2);
========================================

I am trying to save the Dumper output to the database and later trying
to get the same data structure.

Thank You,
HG
 
B

Brian McCauley

Why aren't the outputs of the two print statements same. I want
to reconstruct %hash1 into %hash2.

========================================
use strict;
use Data::Dumper;

my %hash1 = (key1 => 'value1', 'key2' => 'value2');

my %hash2 = eval Dumper(%hash1);

print Dumper(%hash1);

print Dumper(%hash2);
========================================

I am trying to save the Dumper output to the database and later trying
to get the same data structure.

You need to think of Dumper() as taking a single scalar argument


my $hash1 = { key1 => 'value1', 'key2' => 'value2' };

my $hash2 = do { no strict 'vars'; eval Dumper($hash1) };

Note, this has the side effect of creating a package variable $VAR1.

To serialise Perl hashes or arrays into human-readable database large
(text) objects I use.

sub linear_dump {
unless ($dumper) {
$dumper = Data::Dumper->new([]);
$dumper->Indent(0);
}
$dumper->Reset->Values([shift]);
my $dumped = $dumper->Dump;
$dumped =~ s/\A\$VAR1 = [\[{](.*)[\]}];\Z/$1/s or die;
$dumped;
}

sub linear_undump {
no warnings 'uninitialized';
my @data = eval join ' , ' => 'undef' , @_;
die "Error in cached info @_: $@" if $@;
shift @data;
return +{ @data } unless wantarray;
@data;
}

If readability is not an issue consider also using BLOBs and Storable.

Usual caveats about eval(STRING) apply: anyone who can write to the
database can place arbitrary executable code in it. Use this technique
only if you are satisfied that write access to the database is
restricted to people who could edit your scripts anyhow.
 
H

himanshu.garg

Why aren't the outputs of the two print statements same. I want
to reconstruct %hash1 into %hash2.
========================================
use strict;
use Data::Dumper;
my %hash1 = (key1 => 'value1', 'key2' => 'value2');
my %hash2 = eval Dumper(%hash1);
print Dumper(%hash1);
print Dumper(%hash2);
========================================
I am trying to save the Dumper output to the database and later trying
to get the same data structure.

You need to think of Dumper() as taking a single scalar argument

my $hash1 = { key1 => 'value1', 'key2' => 'value2' };

my $hash2 = do { no strict 'vars'; eval Dumper($hash1) };

Note, this has the side effect of creating a package variable $VAR1.

To serialise Perl hashes or arrays into human-readable database large
(text) objects I use.

[code snipped]

If readability is not an issue consider also using BLOBs and Storable.

Usual caveats about eval(STRING) apply: anyone who can write to the
database can place arbitrary executable code in it. Use this technique
only if you are satisfied that write access to the database is
restricted to people who could edit your scripts anyhow.

Thanks for the reply. I will avoid Dumper if that is what is needed
and use XML::Simple instead since readability is not a concern.

Thank You,
HG
 
P

Paul Lalli

Why aren't the outputs of the two print statements same. I want
to reconstruct %hash1 into %hash2.

========================================
use strict;
use Data::Dumper;

my %hash1 = (key1 => 'value1', 'key2' => 'value2');

my %hash2 = eval Dumper(%hash1);

print Dumper(%hash1);

print Dumper(%hash2);
========================================

I am trying to save the Dumper output to the database and later trying
to get the same data structure.

You're making several mistakes with the usage of Data::Dumper.

1) Dumper() takes a list of structures to dump. You are passing it a
list of values (using a hash in a list context). If you want to dump
just the single variable %hash1, you have to pass a reference to that
hash:
print Dumper(\%hash1);
2) Dumper() returns a string that starts with "$VAR1 = ". If you are
trying to eval() that string, you are trying to execute code
containing the variable $VAR1. When you use strict, you need to pre-
declare all your variables. You are eval'ing code without checking
for an error. If you had checked the value of $@, you'd see that the
eval failed because $VAR1 was not previously declared.
3) Because the string that Dumper() returns represents code that
assigns to a reference, if you eval that code, you are getting a
reference out of it. You need to dereference that reference.

There are several solutions to your problem:
(1) Predeclare $VAR1
$ perl -le'
use strict;
use Data::Dumper;
my %hash1 = (key1 => "value1", key2 => "value2");
my $VAR1;
my %hash2 = %{ eval Dumper(\%hash1) };
print Dumper(\%hash1);
print Dumper(\%hash2);
'
$VAR1 = {
'key2' => 'value2',
'key1' => 'value1'
};

$VAR1 = {
'key2' => 'value2',
'key1' => 'value1'
};


(2) Use the Dump() method rather than the Dumper() function, which
lets you set the name you wish to use for the dumped variables:
$ perl -le'
use strict;
use Data::Dumper;
my %hash1 = (key1 => "value1", key2 => "value2");
my $hash2;
eval Data::Dumper->Dump([\%hash1], ["hash2"]);
print Dumper(\%hash1);
print Dumper($hash2);
'
$VAR1 = {
'key2' => 'value2',
'key1' => 'value1'
};

$VAR1 = {
'key2' => 'value2',
'key1' => 'value1'
};

(3) use the Storable module instead, which has (imho) a nicer
interface for this sort of thing, and is also a core module.
$ perl -le'
use strict;
use Storable qw/freeze thaw/;
my %hash1 = (key1 => "value1", key2 => "value2");
my %hash2 = %{ thaw(freeze(\%hash1)) };
use Data::Dumper;
print Dumper(\%hash1, \%hash2);
'
$VAR1 = {
'key2' => 'value2',
'key1' => 'value1'
};
$VAR2 = {
'key2' => 'value2',
'key1' => 'value1'
};


Hope that helps,
Paul Lalli
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top