Data::AsObject - Easy OO access to complex perl data structures
version 0.07
use Data::AsObject qw(dao); my $book = dao { name => "Programming Perl", authors => ["Larry Wall", "Tom Christiansen", "Jon Orwant"], }; print $book->name # prints "Programming Perl" print $book->authors(0) # prints "Larry Wall" my $array_ref = $book->authors # $array_ref is ["Larry Wall", "Tom Christiansen", "Jon Orwant"] my @array = $book->authors->list # @array is ("Larry Wall", "Tom Christiansen", "Jon Orwant") $book->{publisher} = "O'Reilly"; print $book->publisher # prints "O'Reilly"
Data::AsObject
provides easy object-oriented access to complex and arbitrarily nested perl data structures. It is particularly suitable for working with hash-based representation of XML data, as generated by modules like XML::Complie or XML::TreePP.
Version 0.06 of Data::AsObject
broke backward compatibility with two changes that may break existing scripts.
list
method instead.These are some of the reasons why you may want to use Data::AsObject
:
The object-oriented syntax may sometimes be more appropriate than the traditional hashref and arrayref syntax.
Since Data::AsObject
does not preform any autovivification, it protects you from misspelling a hash key when accessing its value (but see also Hash::Util for more robust ways to do that).
If your hashes contain a lot of keys with dashes or colons, as is often the case with keys representing xml element names, Data::AsObject
can automatically access such keys by substituting underscores for the non-standard symbols.
If you have a lot of arrayrefs in your data structure that often need to be traversed, e.g. with grep
, map
or foreach
, Data::AsObject
provides a list
method on arrayrefs to automatically dereference them.
dao
Takes as input one or more hash or array references, and returns one or more objects (Data::AsObject::Hash
or Data::AsObject::Array
respectively) that can be used to access the data structures via an object oriented interface.
Data::AsObject uses Sub::Exporter and allows you to import the dao
sub in one of three modes:
use Data::AsObject dao => { mode => 'strict' };
In this mode (which is the default) dao
will produce an object that dies whenever you try to invoke a hash key that does not exist.
use Data::AsObject dao => { mode => 'loose' };
In this mode dao
will produce an object that returns undef
and issues a warning whenever you try to invoke a hash key that does not exist.
use Data::AsObject dao => { mode => 'silent' };
In this mode dao
will produce an object that returns undef
whenever you try to invoke a hash key that does not exist, but does not complain.
To access hash elements by key, use the hash key as method name:
my $data = dao { three => { two => { one => "kaboom" } } }; print $data->three->two->one; # kaboom
If a hash key contains one or more colons or dashes, you can access its value by substituting underscores for the colons or dashes (the underlying hash key name is not modified).
my $data = dao { 'xml:lang' => "EN", 'element-name' => "some name", }; print $data->xml_lang # "EN" print $data->element_name # "some name"
To access array items pass the item index as an argument to the hash that contains the array:
my $data = dao { uk => ["one", "two", "three", "four"], spain => [ { name => 'spanish', numbers => ["uno", "dos", "tres", "cuatro"] }, { name => 'catalan', numbers => ["un", "dos", "tres", "quatre"] }, ]; }; print $data->en(1) # two print $data->spain(0)->numbers(3); # cuatro
Array of array structures are a little bit clumsier to work with. You will need to use the get
method of Data::AsObject::Array
and pass it the index of the item you want to access:
my $data = dao [ ["one", "two", "three", "four"] ["uno", "dos", "tres", "cuatro"], ["un", "dos", "tres", "quatre"], ]; print $data->get(2)->get(0); # un
Arrayrefs have a dereferencing list
method. For example:
my $data = dao { spain => [ { name => 'spanish', numbers => ["uno", "dos", "tres", "cuatro"] }, { name => 'catalan', numbers => ["un", "dos", "tres", "quatre"] }, ]; }; foreach my $n ( $data->spain->list ) { print $n->name . " "; } # spanish catalan
Data::AsObject
only provides accessor functions. To modify data, access the respective hash or array element directly:
my $data = dao {}; $data->{one} = "uno"; print $data->one # uno
No autovivification is performed by default (but see FUNCTIONS above). An attempt to access a hash or array element that does not exist will produce a fatal error. Use an exception handling mechanism such as Try::Tiny.
use Try::Tiny; my $data = dao { uk => ["one", "two", "three", "four"], spain => ["uno", "dos", "tres", "cuatro"], germany => ["eins", "zwei", "drei", "vier"]. }; try { my $numbers = $data->bulgaria; } catch { warn "No info about Bulgaria!"; };
See also can
below.
Data::AsObject::Hash
and special methodsIf $data
isa Data::AsObject::Hash
:
$data->can
will return the value of the $data->{can}
element. $data->can("some_hash_key")
will properly return undef
if some_hash_key
does not exists, or a reference to a sub that returns $data->{some_hash_key}
otherwise.
my $data = dao { uk => ["one", "two", "three", "four"], # ... }; warn "No info about Bulgaria!" unless $data->can('bulgaria');
Calling $data->VERSION
will attempt to return the value of a hash element with a key "VERSION". Use Data::AsObject->VERSION
instead.
All other special methods and functions (isa
, ref
, DESTROY
) should behave as expected.
Please report any bugs or feature requests to bug-data-object at rt.cpan.org
, or through the web interface at http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Data-Object. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.
Peter Shangov <pshangov@yahoo.com>
This software is copyright (c) 2011 by Peter Shangov.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.