sub clean { our $node; local *node = \$_[0]; # Alias return if !defined($node); my $reftype = ref($node); return if !$reftype; if ($reftype eq 'REF' || $reftype eq 'SCALAR') { clean($$node); $node = undef if !defined($$node); } elsif ($reftype eq 'ARRAY') { clean($_) for @$node; @$node = grep defined, @$node; $node = undef if !@$node; } elsif ($reftype eq 'HASH') { clean($_) for values(%$node); delete @{$node}{ grep !defined($node->{$_}), keys(%$node) }; $node = undef if !keys(%$node); } } #### use strict; use warnings; use Data::Dumper qw( Dumper ); sub dumper { local $Data::Dumper::Useqq = 1; local $Data::Dumper::Terse = 1; local $Data::Dumper::Indent = 0; return Dumper($_[0]); } for ( [ [1], [], {1 => 2, 2 =>{} } ], [ undef, [ undef ], { x => undef }, \undef, \\\undef ], ) { my $d = $_; print(dumper($d), "\n"); clean($d); print(dumper($d), "\n"); print("\n"); } #### [[1],[],{1 => 2,2 => {}}] [[1],{1 => 2}] [undef,[undef],{"x" => undef},\undef,\\$VAR1->[3]] undef