Data::Dumper::Overload

Ovid on 2008-06-23T16:16:14

Dear Lazyweb: tell me that there's a Data::Dumper (or better yet, Data::Dump::Streamer) alternative that allows me to respect string overloading. Specifically, I need to have a Data::Dumper-like module which accepts a hashref of which overloaded modules to respect for string overloading (sometimes I want all, sometimes I want none). Or better still, a callback system whereby I can specify how a particular data structure gets represented when dumped. I hack together the following, but it was for a very specific, internal need. Thus, it's probably useless for your purposes, but it suits mine perfectly (and it's a one-shot deal and not designed to live beyond a few hours).

package PrettyDumper;

use strict;
use warnings;
use Scalar::Util qw(blessed reftype);
use Clone 'clone';
use Sub::Information as => 'inspect';
use Carp 'croak';
require overload;

use Exporter::NoWork;
my %dispatch = (
    ''      => sub { shift || '' },
    'ARRAY' => \&_array,
    'HASH'  => \&_hash,
    'CODE'  => sub { inspect(shift)->code },
);

sub pretty_dump {
    my $thing = clone(shift);
    require Data::Dumper;
    local $Data::Dumper::Terse = 1;
    chomp( my $dump =  Data::Dumper::Dumper(_pretty_dump($thing)) );
    return $dump;
}

sub _pretty_dump {
    my $thing = shift;
    my $ref = reftype($thing) || '';
    if ( my $dispatch = $dispatch{$ref} ) {
        return $dispatch->($thing);
    }
    return Data::Dumper::Dumper($thing);
}

sub _array {
    my $array = shift;
    if ( overload::Overloaded($array) ) {
        if ( my $method = overload::Method( $array, '""' ) ) {
            return $array->$method;
        }
    }
    else {
        foreach (@$array) {
            $_ = _pretty_dump($_);
        }
    }
    return $array;
}

sub _hash {
    my $hash = shift;
    if ( overload::Overloaded($hash) ) {
        if ( my $method = overload::Method( $hash, '""' ) ) {
            return $hash->$method;
        }
    }
    else {
        foreach (keys %$hash) {
            $hash->{$_} = _pretty_dump($hash->{$_});
        }
    }
    return $hash;
}

1;

It doesn't offer me the 'per package' control that I want, but it's close enough for what I need.


Data::Dump::Streamer has a hook for this

btilly on 2008-06-23T18:06:53

Here is a demonstration.

use Data::Dump::Streamer;
my $obj = bless {}, "Foo";
Dump($obj)->Out;
Dump($obj)->Freezer(
        "Foo", sub {my $self = shift; "$self"}
    )->Out;

Now obviously in this case Foo does not have a useful stringify method. But if it did, it would be used.

Shooting off on a tangent...

pjm on 2008-06-24T06:23:01

Hearing you in the vicinity of the Data::Dumper namespace just reminded me that I'm long overdue in sending thanks for creating Data::Dumper::Simple. It's one of those modules that just happily motors into place when required, does its job without any fuss, and produces exactly what I want to see.

So... thanks,

Paul

Re:Shooting off on a tangent...

Ovid on 2008-06-24T08:54:23

Thanks you! It's always good to get feedback about what people do and don't like about my code (especially the "do like" bits). Since it's based on a source filter, I was given a bit of grief over its creation, but I'm pleasantly surprised by people's reactions to it. My favorite is woman back in the States who tells me that she can never hate me because she uses Data::Dumper::Simple so much that it would make her mad every time she programs :)

Re:Shooting off on a tangent...

Aristotle on 2008-06-24T09:28:29

Ovid and the women… ;-)

Re:Shooting off on a tangent...

Ovid on 2008-06-24T09:36:26

Regrettably, any woman with even the remotest interest in me seems to be doomed to live in a different country. I want to find this "Fate" guy and put the boot in a few times.