perl.gg / hidden-gems

Serializing Data

2024-07-03

SERIALIZING COMPLEX DATA STRUCTURES WITH DATA::DUMPER

Need to save a complex Perl data structure to a file and load it back later? Data::Dumper is your friend. It's been in Perl's core since version 5.005, so it's available everywhere.

Let's see how to use it properly.

Part 1: THE BASICS

Data::Dumper converts Perl data structures into valid Perl code that, when evaluated, recreates the original structure.
use Data::Dumper; my $data = { name => "Alice", scores => [95, 87, 92], meta => { level => "advanced", active => 1, }, }; print Dumper($data);
This outputs something like:
$VAR1 = { 'name' => 'Alice', 'meta' => { 'active' => 1, 'level' => 'advanced' }, 'scores' => [ 95, 87, 92 ] };

Part 2: CONFIGURING DATA::DUMPER FOR SERIALIZATION

The default output is great for debugging, but for serialization we want specific settings. Here's the magic combination:
use Data::Dumper; $Data::Dumper::Purity = 1; # Handle self-references $Data::Dumper::Indent = 1; # Readable indentation $Data::Dumper::Sortkeys = 1; # Consistent key ordering $Data::Dumper::Terse = 1; # No $VAR1 = prefix
Let's break down what each setting does: Purity = 1
Ensures the output can handle circular references and self-referential structures. Essential for complex data.
Indent = 1
Uses a readable indentation style. Options are: 0 = no indentation (compact) 1 = fixed indentation (clean) 2 = variable indentation based on depth 3 = similar to 2 with extra newlines
Sortkeys = 1
Sorts hash keys alphabetically. This makes the output deterministic - same data always produces same output. Great for version control and diffing.
Terse = 1
Omits the "$VAR1 = " prefix. The output is just the data structure itself, ready for assignment.

Part 3: SAVING TO A FILE

Here's how to save a complex structure:
use Data::Dumper; my $config = { database => { host => "localhost", port => 5432, name => "myapp", settings => { pool_size => 10, timeout => 30, ssl_enabled => 1, }, }, features => ["auth", "logging", "caching"], version => "2.1.0", }; # Configure Dumper $Data::Dumper::Purity = 1; $Data::Dumper::Indent = 1; $Data::Dumper::Sortkeys = 1; $Data::Dumper::Terse = 1; # Save to file open(my $fh, '>', './config.dat') or die "Cannot open: $!"; print $fh Dumper($config); close($fh);
The resulting file looks like:
{ 'database' => { 'host' => 'localhost', 'name' => 'myapp', 'port' => 5432, 'settings' => { 'pool_size' => 10, 'ssl_enabled' => 1, 'timeout' => 30 } }, 'features' => [ 'auth', 'logging', 'caching' ], 'version' => '2.1.0' }
Notice how the hash keys are sorted alphabetically. That's Sortkeys at work.

Part 4: RESTORING FROM A FILE

Loading the data back is beautifully simple with 'do':
my $restored = do "./config.dat" or die "Cannot load: $!"; # Now $restored is a hashref with all your data print "Database host: $restored->{database}{host}\n"; print "Features: @{$restored->{features}}\n";
The 'do' operator reads the file and evaluates it as Perl code. Since Data::Dumper outputs valid Perl, this recreates your exact data structure.

Always check for errors:

my $restored = do "./config.dat"; if ($@) { die "Parse error: $@"; } if (!defined $restored) { die "Cannot read file: $!"; }

Part 5: NESTED STRUCTURES

Data::Dumper handles arbitrarily complex nesting:
my $company = { name => "TechCorp", employees => [ { name => "Alice", role => "Developer", skills => ["Perl", "Python", "Go"], contact => { email => "alice\@techcorp.com", phone => "555-0101", }, }, { name => "Bob", role => "Designer", skills => ["Figma", "CSS", "SVG"], contact => { email => "bob\@techcorp.com", phone => "555-0102", }, }, ], locations => ["NYC", "London", "Tokyo"], founded => 2015, }; # Save it open(my $fh, '>', './company.dat') or die $!; print $fh Dumper($company); close($fh); # Load it back my $loaded = do "./company.dat" or die $!; # Access deeply nested data print "First employee's first skill: "; print "$loaded->{employees}[0]{skills}[0]\n"; # Output: First employee's first skill: Perl

Part 6: A COMPLETE SAVE/LOAD MODULE

Here's a reusable pattern:
package DataStore; use strict; use warnings; use Data::Dumper; $Data::Dumper::Purity = 1; $Data::Dumper::Indent = 1; $Data::Dumper::Sortkeys = 1; $Data::Dumper::Terse = 1; sub save { my ($file, $data) = @_; open(my $fh, '>', $file) or die "Cannot save to $file: $!"; print $fh Dumper($data); close($fh); return 1; } sub load { my ($file) = @_; my $data = do $file; die "Parse error in $file: $@" if $@; die "Cannot read $file: $!" if !defined $data; return $data; } 1;
Usage:
use DataStore; my $settings = { theme => "dark", font_size => 14 }; DataStore::save("./settings.dat", $settings); my $loaded = DataStore::load("./settings.dat"); print "Theme: $loaded->{theme}\n";
CONCLUSION

Data::Dumper with the right settings is a simple, reliable way to serialize Perl data structures. The key settings to remember:

$Data::Dumper::Purity = 1; # Safe for complex refs $Data::Dumper::Indent = 1; # Readable output $Data::Dumper::Sortkeys = 1; # Deterministic ordering $Data::Dumper::Terse = 1; # Clean output
Save with print $fh Dumper($data), restore with do $file.

For more complex needs, consider JSON::XS, Storable, or YAML::XS - but for pure Perl simplicity, Data::Dumper is hard to beat.

perl.gg