One of the all time most useful Perl modules is Data::Dumper. It can be used to dump out any - well, almost any - data structure as Perl code that allows you to see what's in it. This is invaluable when you're debugging.
One of the other great uses of Data::Dumper is for simple data
persistence. You can eval
back in a structure printed out with
Dumper
and recreate the data structure. You can use this for
technique for saving data between program runs, or communicating data
between other Perl programs. The biggest advantage is that if you
understand Perl data structures, then it's easy to edit the data
structures by hand.
This, however, is a big disadvantage if you don't understand Perl data structures. For example, if you're using Data::Dumper to create a config file, then you'd better hope the admin can program Perl. Likewise if you want a program to read the file, then that program better be Perl. If you're trying to communicate your output to a Java program then you have a problem.
The biggest disadvantage of using Data::Dumper is however that unless you trust the data source then you can't eval it - the file could contain malicious code rather than a Data::Dumper data structure.
Enter YAML. YAML is alternative data structure language that is human readable, cross platform (Perl, Python, Java) and most importantly eval safe.
To demonstrate this let's create a data structure that repents the IMDB's top three films.
#!/usr/bin/perl
# turn on perl's safety procedures use strict; use warnings;
# load the URI module use URI;
# build a list of IMDB's current top films my @top_films;
my %godfather = ( name => "Godfather, The", stars => { "Marlon Brando" => "Don Vito Corleone", "Al Pacino" => "Michael 'Mike' Corleone", "Diane Keaton" => "Kay Adams-Corleone", }, year => 1972, url => "http://us.imdb.com/Title?0068646");
push @top_films, \%godfather;
my %shawshank = ( name => "Shawshank Redemption, The", stars => { "Tim Robbins" => "Andy Dufresne", "Morgan Freeman" => "Ellis Boyd 'Red' Redding", "Bob Gunton" => "Warden Samuel Norton", }, year => 1994, url => "http://us.imdb.com/Title?0111161");
push @top_films, \%shawshank;
my %godfather2 = ( name => "Godfather: Part 2, The", stars => { "Al Pacino" => "Michael 'Mike' Corleone", "Robert Duvall" => "Tom Hagen", "Diane Keaton" => "Kay Adams-Corleone", }, year => 1974, url => "http://us.imdb.com/Title?0071562");
push @top_films, \%godfather2;
And then print out the with Data::Dumper:
use IO::File; my $fh = IO::File->new("dumper",">") or die "Can't open 'dumper': $!)
use Data::Dumper; print {$fh} Dumper \@top_films;
Which produces a file that looks like:
$VAR1 = [ { 'stars' => { 'Diane Keaton' => 'Kay Adams-Corleone', 'Marlon Brando' => 'Don Vito Corleone', 'Al Pacino' => 'Michael \'Mike\' Corleone' }, 'url' => 'http://us.imdb.com/Title?0068646', 'name' => 'Godfather, The', 'year' => 1972 }, { 'stars' => { 'Morgan Freeman' => 'Ellis Boyd \'Red\' Redding', 'Tim Robbins' => 'Andy Dufresne', 'Bob Gunton' => 'Warden Samuel Norton' }, 'url' => 'http://us.imdb.com/Title?0111161', 'name' => 'Shawshank Redemption, The', 'year' => 1994 }, { 'stars' => { 'Diane Keaton' => 'Kay Adams-Corleone', 'Al Pacino' => 'Michael \'Mike\' Corleone', 'Robert Duvall' => 'Tom Hagen' }, 'url' => 'http://us.imdb.com/Title?0071562', 'name' => 'Godfather: Part 2, The', 'year' => 1974 } ];
That can then be read back in with eval
like so:
use IO::File; my $fh2 = IO::File->new("dumper","<") or die "Can't open 'dumper': $!)
my @films_dumper; { # slurp in the whole file, rather than # a line at a time local $/;
# load all the data my $data = <$fh>;
@films_dumper = @{ eval $data }; }
Now let's see how that works with YAML
my $fh3 = IO::File->new("yaml",">") or die "Can't open 'yaml': $!)
use YAML; print {$fh3} Dump \@top_films;
And that produces output like this
--- #YAML:1.0 - name: Godfather, The stars: Al Pacino: Michael 'Mike' Corleone Diane Keaton: Kay Adams-Corleone Marlon Brando: Don Vito Corleone url: http://us.imdb.com/Title?0068646 year: 1972 - name: Shawshank Redemption, The stars: Bob Gunton: Warden Samuel Norton Morgan Freeman: Ellis Boyd 'Red' Redding Tim Robbins: Andy Dufresne url: http://us.imdb.com/Title?0111161 year: 1994 - name: 'Godfather: Part 2, The' stars: Al Pacino: Michael 'Mike' Corleone Diane Keaton: Kay Adams-Corleone Robert Duvall: Tom Hagen url: http://us.imdb.com/Title?0071562 year: 1974
I'll hope you'll agree with me that the output is quite easy to understand. This can be read back in like so
use IO::File; my $fh4 = IO::File->new("yaml","<") or die "Can't open 'yaml': $!)
my @films_yaml; { # slurp in the whole file, rather than # a line at a time local $/;
# load all the data my $data = <$fh4>;
@films_yaml = @{ Load($data) }; }