"it didn't look like I could provide multiple keys"
Ask and you shall receive. Oh wait, you didn't ask, well no matter...
#!/usr/bin/perl
use strict; # https://perlmonks.org/?node_id=11111952
use warnings;
use List::Util qw( none any );
use Data::Dump qw( dd );
sub subtree
{
my ($key, $tree) = @_;
if( ref $tree eq 'ARRAY' )
{
my @items = map [ subtree( $key, $_ ) ], @$tree;
return +(none { $_->[0] } @items ) ? ( 0, []) :
( 1, [ map { $_->[0] ? $_->[1] : undef } @items ] );
}
elsif( ref $tree eq 'HASH' )
{
my @wanted;
for my $k ( sort keys %$tree )
{
if( matchkey( $key, $k ) ) { push @wanted, [ 1, $k => $tree->{$k
+} ] }
else
{
my ( $w, $t ) = subtree( $key, $tree->{$k} );
$w and push @wanted, [ $w, $k => $t ];
}
}
return @wanted > 0, +{ map { @{ $_ }[1, 2] } @wanted };
}
else { return 0, $tree }
}
sub matchkey
{
my ($key, $here) = @_;
any { $_ eq $here } ref $key ? @$key : $key;
}
sub pathforkey
{
my ($key, $tree, $sofar) = @_;
if( ref $tree eq 'HASH' )
{
return map {
matchkey( $key, $_ ) ? $sofar . "{$_}" : (),
pathforkey( $key, $tree->{$_}, $sofar . "{$_}" )
} sort keys %$tree;
}
elsif( ref $tree eq 'ARRAY' )
{
return map { pathforkey( $key, $tree->[$_], $sofar . "[$_]" )
} 0 .. $#$tree;
}
else { return () }
}
my $tree = gettree();
dd 'original tree', $tree;
print "\n";
my ($want, $subtree) = subtree( [ 'field', '_mcid' ], $tree );
dd "the subtree for 'field' ", $subtree;
print "\nall paths to key 'field' :\n";
print "$_\n" for pathforkey( ['field', '_mcid'], $tree, '' );
sub gettree # slightly reduced...
{
my $tree = { 'cookies' => { '_AVESTA_ENVIRONMENT' => 'prod',
'_mcid' => '1.340667ccb3eb6552450356561ab6bd92.' },
'error' => '400 Bad Request',
'content' => { 'detail' =>
'The resource specific details, \'errors\' array.',
'errors' => [ 'not this', { 'message' => 'This value of type obj
+ect.',
'field' => 'merge_fields' } ],
'status' => 400,
'title' => 'Invalid Resource',
'type' => 'http://developer.mailchimp.',
'instance' => '59edf1fc-ed93-4a40-ba23-1f0af24a6eb3' },
'code' => '400' };
}
Outputs:
(
"original tree",
{
code => 400,
content => {
detail => "The resource specific details, 'errors'
+array.",
errors => [
"not this",
{ field => "merge_fields", message => "
+This value of type object." },
],
instance => "59edf1fc-ed93-4a40-ba23-1f0af24a6eb3",
status => 400,
title => "Invalid Resource",
type => "http://developer.mailchimp.",
},
cookies => {
_AVESTA_ENVIRONMENT => "prod",
_mcid => "1.340667ccb3eb6552450356561ab6bd92.",
},
error => "400 Bad Request",
},
)
(
"the subtree for 'field' ",
{
content => { errors => [undef, { field => "merge_fields" }] },
cookies => { _mcid => "1.340667ccb3eb6552450356561ab6bd92." },
},
)
all paths to key :
{content}{errors}[1]{field}
{cookies}{_mcid}
|