rovf has asked for the wisdom of the Perl Monks concerning the following question:

Assuming the code like this:

use Data::Dumper; my $hashref={ ...., k1 => { .... k2 => { .... kN => {...., mydata => MyClass->new(), .... }}}}; print(Dumper($hashref));
the printout will contain somewhere something like
.... mydata => bless(..., 'MyClass') ....
I'm looking for a way to get $hashref pretty-printed, so that the result looks like this:
.... mydata => 'MyOwnRepresentation of the MyClass instance' ....
Note that the original hash should not be changed, and I don't know at compile time, where the mydata key is buried inside the hash. I even don't know whether it's name really is 'mydata'. I only know that somewhere in the hash are some data of type MyClass, and these are the ones where I want to take control on how they are pretty printed.

My first idea was to set

sub MyClass::myfreezer { ... } $Data::Dumper::Freeze='myfreezer'
and handle everythin in myfreezer, but as far I can see, a freeze function can only change the internals to the object to be frozen. Is it possible to find a way (without writing a new pretty-printer from scratch)?

I also had a look at Data::Dumper::Streamer, which seems to have a more flexible "Freeze", but still I don't see how this can be achieved.

-- 
Ronald Fischer <ynnor@mm.st>

Replies are listed 'Best First'.
Re: Fine grain control over Data::Dumper
by ig (Vicar) on May 28, 2009 at 13:39 UTC

    In the pure Perl implementation of Data::Dumper, output for blessed references is produced in Data::Dumper::_dump(). If the Freezer method is defined and the object supports that method, the freezer method is called to prepare the object before it is dumped, but it is otherwise dumped in the same way as any other object, producing the same style of output.

    There are no hooks in _dump() to easily override the formatting of blessed references. On the other hand, if you can live with the performance of the pure Perl implementation, it is just Perl and it would not be too difficult to change it to detect your object type and display it differently.

Re: Fine grain control over Data::Dumper
by kennethk (Abbot) on May 28, 2009 at 14:18 UTC
    Another possibility you may consider is writing a wrapper object that @ISA  = qw(Data::Dumper). Should be a fairly simple task of writing sub _dump such that it tests to see of the object class matches yours, and if not, invokes SUPER::_dump. If you're not familiar with OO in Perl, Overridden Methods has a pretty good summary.

      UPDATE: I FOUND THE BUG!

      I should not have called $class->SUPER::Dumper(@args);, but $class->SUPER::Dump(@args);, because Dumper() always blesses into a Data::Dumper object.

      To my surprise, I found it more difficult to override _dump then expected. Maybe you can spot the error? I started like this:

      package PpDumper; # PpDumper is a subclass of Data::Dumper, which provides # a custom _dump() method use Data::Dumper; our @ISA='Data::Dumper'; sub _dump { my ($self, $val, $name) = @_; print "my _dump called\n"; (ref($val) && $val->can('pp')) ? $val->pp($name) : $self->SUPER::_dump($val,$name); } sub PpDumper::Dumper { my ($class,@args) = @_; print "my own Dumper called\n"; $class->SUPER::Dumper(@args); } package main; .... my $h = { ... } { local $Data::Dumper::Useperl=1; print("3:\n",PpDumper->Dumper($h),"\n"); }
      When I run this, I see in the output of course my own Dumper called, but I don't see my _dump called being printed. This means that my custom _dump routine has not been called. This is strange: I verified that Data::Dumper::new (which is eventually called by Data::Dumper::Dumper) uses the two-argument form of bless, so my object should be of type PpDumper. Also, setting Useperl to 1 should ensure that no compiled components get in my way (I don't know whether this is necessary for overriding methods, so I put it there for the safe side).

      Where is the bug?

      -- 
      Ronald Fischer <ynnor@mm.st>
      That was my first thought, then I realised the presence of the leading _ (underscore) in _dump ... and we all know what that implies :-D

      or, put another way, overloading a private method may (and indeed probably will) result in problems down the line.

      A user level that continues to overstate my experience :-))

      This sounds interesting, and maybe I'll go this way. The main drawback here is that we are relying on an undocumented interface. In case we upgrade to a new version of Perl, with maybe a new verion of dumper, it might break our code. Still, I think I'll give it a try.

      -- 
      Ronald Fischer <ynnor@mm.st>