Perl Data::Dumper and Data::Printer
last modified November 7, 2026
Perl programs build nested data structures out of hashes, arrays, and
references. Printing such a structure with print only shows
something like HASH(0x55d1c0a8e2a8). The core module
Data::Dumper turns any structure into readable Perl source code,
which makes it the standard tool for a quick look at data while debugging. The
CPAN module Data::Printer produces a more compact view meant for
humans, with extra details about the values.
Data::Dumper ships with Perl; Data::Printer is
installed with cpanm Data::Printer. The examples were run with Perl
5.44, Data::Dumper 2.192, and Data::Printer 1.002001
on Linux.
Dumping a structure
The Dumper function takes a list of values and returns a string.
Structures are passed as references.
#!/usr/bin/perl
use strict;
use warnings;
use v5.34.0;
use Data::Dumper;
my %user = (
name => 'Tomas',
age => 34,
langs => ['Perl', 'Go', 'SQL'],
address => {
city => 'Kosice',
zip => '04001',
},
);
my @scores = (88, 92.5, 'n/a');
print Dumper(\%user);
print Dumper(\@scores, 'plain string');
Each value is printed as an assignment to a variable named
$VAR1, $VAR2, and so on, so the output is valid Perl
code. Nested hashes and arrays are shown with braces and brackets. Numbers
that are stored as integers appear without quotes, while other values, including
the floating-point 92.5, are quoted. The keys of %user come out in
Perl's random hash order, which differs from run to run; the next section fixes
that.
$ perl basic.pl
$VAR1 = {
'age' => 34,
'address' => {
'zip' => '04001',
'city' => 'Kosice'
},
'name' => 'Tomas',
'langs' => [
'Perl',
'Go',
'SQL'
]
};
$VAR1 = [
88,
'92.5',
'n/a'
];
$VAR2 = 'plain string';
Indent, Sortkeys, and Terse
The output is controlled by package variables of the form
$Data::Dumper::Name. Three of them are set in almost every
program.
#!/usr/bin/perl
use strict;
use warnings;
use v5.34.0;
use Data::Dumper;
my $data = { b => [1, 2], a => { x => 1 }, c => 'text' };
$Data::Dumper::Sortkeys = 1;
for my $indent (0, 1, 2) {
local $Data::Dumper::Indent = $indent;
say "Indent = $indent:";
print Dumper($data);
print "\n" if $indent == 0;
}
{
local $Data::Dumper::Terse = 1;
local $Data::Dumper::Indent = 1;
say 'Terse = 1:';
print Dumper($data);
}
Sortkeys set to a true value sorts hash keys alphabetically, which
makes the output stable and comparable between runs. Indent chooses
the layout: 0 puts everything on one line, 1 indents each level by a fixed two
spaces, and the default 2 aligns nested structures under their opening bracket,
which quickly wastes width. Terse drops the
$VAR1 = prefix and the final semicolon and prints just the value.
Using local limits a change to the enclosing block, so other code
that uses the module is not affected.
$ perl settings.pl
Indent = 0:
$VAR1 = {'a' => {'x' => 1},'b' => [1,2],'c' => 'text'};
Indent = 1:
$VAR1 = {
'a' => {
'x' => 1
},
'b' => [
1,
2
],
'c' => 'text'
};
Indent = 2:
$VAR1 = {
'a' => {
'x' => 1
},
'b' => [
1,
2
],
'c' => 'text'
};
Terse = 1:
{
'a' => {
'x' => 1
},
'b' => [
1,
2
],
'c' => 'text'
}
The object interface
Global variables affect every caller in the program. The object interface keeps the settings in one dumper object and also lets us name the variables.
#!/usr/bin/perl
use strict;
use warnings;
use v5.34.0;
use Data::Dumper;
my $config = {
port => 8080,
hosts => ['alpha', 'beta'],
debug => 0,
message => "Hello\tworld\n",
};
my @langs = qw(Perl Raku);
my $d = Data::Dumper->new([$config, \@langs], [qw(config *langs)]);
$d->Indent(1)->Sortkeys(1)->Useqq(1);
print $d->Dump;
say Data::Dumper->new([$config])->Terse(1)->Indent(0)->Sortkeys(1)->Dump;
The constructor takes a reference to the list of values and a reference to the
list of names. A name starting with * dumps an array or hash
reference as a real array or hash, here @langs = (...). Each
setting has a method of the same name that returns the object, so the calls
chain. Useqq uses double-quoted strings with escapes, which makes
the tab and the newline in message visible. The last line creates a
second dumper without Useqq; its single-quoted output contains the
raw tab and newline characters, which break the line in the middle of the
string.
$ perl oo.pl
$config = {
"debug" => 0,
"hosts" => [
"alpha",
"beta"
],
"message" => "Hello\tworld\n",
"port" => 8080
};
@langs = (
"Perl",
"Raku"
);
{'debug' => 0,'hosts' => ['alpha','beta'],'message' => 'Hello world
','port' => 8080}
Custom key order
Sortkeys also accepts a code reference. It receives each hash
reference to be dumped and returns a reference to an array of the keys to show,
in the order to show them.
#!/usr/bin/perl
use strict;
use warnings;
use v5.34.0;
use Data::Dumper;
my %record = (id => 7, name => 'Lamp', price => 19.9, _internal => 'x', created => '2026-11-07');
local $Data::Dumper::Indent = 1;
local $Data::Dumper::Terse = 1;
local $Data::Dumper::Sortkeys = sub {
my $h = shift;
my @keys = grep { !/^_/ } keys %$h;
my %rank = (id => 0, name => 1);
return [ sort { ($rank{$a} // 9) <=> ($rank{$b} // 9) or $a cmp $b } @keys ];
};
print Dumper(\%record);
The function hides keys that start with an underscore and puts
id and name first, followed by the remaining keys in
alphabetical order. Since only the returned keys are printed, the same
mechanism filters out bulky or sensitive fields from debug output.
$ perl sortkeys.pl
{
'id' => 7,
'name' => 'Lamp',
'created' => '2026-11-07',
'price' => '19.9'
}
Limiting the depth
A deep structure can produce pages of output. Maxdepth stops
descending after the given number of levels.
#!/usr/bin/perl
use strict;
use warnings;
use v5.34.0;
use Data::Dumper;
my $tree = {
name => 'root',
kids => [
{ name => 'a', kids => [ { name => 'a1', kids => [] } ] },
{ name => 'b', kids => [] },
],
};
local $Data::Dumper::Sortkeys = 1;
local $Data::Dumper::Terse = 1;
local $Data::Dumper::Indent = 1;
local $Data::Dumper::Maxdepth = 2;
print Dumper($tree);
With Maxdepth 2, the dumper shows the top-level hash and the
kids array, but prints the hashes inside the array as their
addresses. The addresses differ between runs. This gives a quick overview of
the shape of large data, for example a decoded JSON response, before looking
at the details.
$ perl depth.pl
{
'kids' => [
'HASH(0x58b64839c9b8)',
'HASH(0x58b64839cbf8)'
],
'name' => 'root'
}
Shared references, cycles, and objects
Data::Dumper notices when the same reference appears more than
once, including references that point back to themselves, and shows blessed
references and code references as well.
#!/usr/bin/perl
use strict;
use warnings;
use v5.34.0;
use Data::Dumper;
$Data::Dumper::Sortkeys = 1;
$Data::Dumper::Indent = 1;
my $shared = { color => 'red' };
my $pair = { left => $shared, right => $shared };
print Dumper($pair);
my $node = { name => 'loop' };
$node->{self} = $node;
print Dumper($node);
my $obj = bless { id => 42 }, 'My::Item';
my $code = sub { return 1 };
print Dumper($obj, $code);
The second occurrence of a shared hash is printed as a path to the first one,
$VAR1->{'left'}, so it is clear that both keys refer to the same
hash and not to two equal copies. A cycle is shown in the same way, which keeps
the dumper from recursing forever. An object is printed with a
bless call naming its class. Code is not dumped; a code reference
appears as sub { "DUMMY" } unless $Data::Dumper::Deparse
is set, in which case the module decompiles the subroutine with
B::Deparse.
$ perl refs.pl
$VAR1 = {
'left' => {
'color' => 'red'
},
'right' => $VAR1->{'left'}
};
$VAR1 = {
'name' => 'loop',
'self' => $VAR1
};
$VAR1 = bless( {
'id' => 42
}, 'My::Item' );
$VAR2 = sub { "DUMMY" };
Reading the data back
Since the output is Perl code, evaluating it rebuilds the structure. This makes
Data::Dumper a simple serialization format for Perl-only data.
#!/usr/bin/perl
use strict;
use warnings;
use v5.34.0;
use Data::Dumper;
my $settings = {
theme => 'dark',
recent => ['notes.txt', 'todo.md'],
window => { width => 1024, height => 768 },
};
my $text = Data::Dumper->new([$settings])->Terse(1)->Indent(1)->Sortkeys(1)->Dump;
open my $out, '>', 'settings.txt' or die "settings.txt: $!";
print $out $text;
close $out;
open my $in, '<', 'settings.txt' or die "settings.txt: $!";
my $code = do { local $/; <$in> };
close $in;
my $loaded = eval $code;
die "cannot load settings: $@" if $@;
print $code;
say "theme: $loaded->{theme}";
say "width: $loaded->{window}{width}";
say "recent: @{ $loaded->{recent} }";
The structure is dumped in Terse mode, so the file contains just
an expression, and a string eval returns its value. A structure
with shared or circular references needs the Purity setting, which
adds statements to restore the links. Evaluating a file runs arbitrary code, so
this is acceptable only for files that the program wrote itself. For data
exchanged with other programs or users, JSON is the safer and more portable
choice.
$ perl roundtrip.pl
{
'recent' => [
'notes.txt',
'todo.md'
],
'theme' => 'dark',
'window' => {
'height' => 768,
'width' => 1024
}
}
theme: dark
width: 1024
recent: notes.txt todo.md
Data::Printer
Data::Printer is designed for reading rather than for
evaluation. Its p function prints a variable to standard error, and
np returns the text instead. The short alias DDP
loads the module.
#!/usr/bin/perl
use strict;
use warnings;
use v5.34.0;
use DDP colored => 0;
my %user = (
name => 'Tomas',
age => 34,
langs => ['Perl', 'Go', 'SQL'],
address => { city => 'Kosice', zip => '04001' },
active => undef,
);
p %user;
my @matrix = ([1, 2], [3, 4]);
p @matrix;
my $text = np @matrix, multiline => 0;
say "as string: $text";
Unlike Dumper, p takes the variable itself, not a
reference. Keys are sorted, array elements are numbered, and strings are
quoted while numbers are not. The value undef is shown explicitly,
and the module points out that the string "04001" also has the
numeric value 4001, a detail that matters for postal codes and identifiers.
Options follow the variable; multiline => 0 produces a single
line. Colours are on by default when writing to a terminal; the example turns
them off with colored => 0 so the output can be shown here.
$ perl ddp.pl
{
active undef,
address {
city "Kosice",
zip "04001" (dualvar: 4001)
},
age 34,
langs [
[0] "Perl",
[1] "Go",
[2] "SQL"
],
name "Tomas"
}
[
[0] [
[0] 1,
[1] 2
],
[1] [
[0] 3,
[1] 4
]
]
as string: [ [ 1, 2 ], [ 3, 4 ] ]
Objects with Data::Printer
For objects, Data::Printer shows more than the internal hash: it
lists the class's methods and the inheritance tree.
#!/usr/bin/perl
package Counter;
sub new { my ($class, %args) = @_; return bless { count => $args{start} // 0 }, $class }
sub inc { $_[0]{count}++ }
sub value { $_[0]{count} }
package main;
use strict;
use warnings;
use v5.34.0;
use DDP colored => 0;
my $c = Counter->new(start => 5);
$c->inc;
p $c;
my $data = { regex => qr/^\d+$/i, code => \&Counter::inc, num => 3.14, str => '3.14' };
p $data;
The Counter object is printed with its public and private methods,
where private means a name starting with an underscore, followed by its
internal data. A regular expression is shown as its pattern with its
modifiers, and a code reference as sub { ... }. Settings can be
stored in a .dataprinter file in the home directory, so a project
does not need to repeat them in every use line.
$ perl ddp_obj.pl
Counter {
public methods (3): inc, new, value
private methods (0)
internals: {
count 6
}
}
{
code sub { ... },
num 3.14,
regex ^\d+$ (modifiers: ui),
str 3.14
}
Best practices
- Always sort keys: set
Sortkeysso that dumps are stable and can be compared withdiff. - Prefer Indent 1: it keeps deep structures readable without the wide alignment of the default.
- Localize settings: change the
$Data::Dumper::variables withlocal, or use the object interface. - Dump to STDERR while debugging:
warn Dumper($x)keeps debug output out of the program's real output, and so doesp. - Do not eval untrusted dumps: use JSON for data that crosses program boundaries.
- Use Data::Printer for exploration: its output is easier to read and shows details such as numeric strings and object methods.
In this article we have inspected data structures with
Data::Dumper, configured its output with Indent,
Sortkeys, Terse, Useqq, and
Maxdepth, dumped shared references, cycles, and objects, read a dump
back with eval, and explored data with
Data::Printer.
Source
Data::Dumper ยท Data::Printer on MetaCPAN
Author
List all Perl tutorials.