Douglas Douglas - 10 months ago 29
Perl Question

Accessing JSON decoded into a HASH and an array of hash references

Given the following dumper output is there a way to iterate through each hash to list only the items under each

record? I want to be able to say things like:

print $results{1342}{'domain'};

and have the statement return
as a result.

Would I have to first read through all of
array and then use
to access the data in there ? I'm not sure how to proceed.

$VAR1 = {
'end_time' => 1466017739,
'options' => {
'hour_offset' => '00',
'timezone' => 'America/New_York'
'field_headers' => {
'priority' => 'Priority',
'status' => 'Status',
'assignee_external_id' => 'Assignee external id',
'initially_assigned_at' => 'Initially assigned at'
'results' => [
'priority' => 'High',
'status' => 'Open',
'domain' => '',
'generated_timestamp' => 1546547669,
'id' => 1342
'priority' => 'Low',
'status' => 'Open',
'domain' => '',
'generated_timestamp' => 1464567669,
'id' => 7062
'priority' => 'Low',
'status' => 'Closed',
'domain' => '',
'generated_timestamp' => 1464267669,
'id' => 432

Answer Source

Your dump shows a hashref containing a scalar, two hashrefs and an arrayref. The arrayref has hashrefs for elements. If you want to retrieve specific elements from it, you need to know the index.

$top_level->{results}->[0]->{domain};  # is ''
$top_level->{results}->[0]->{status};  # is 'open'

To iterate through it dereference the array

foreach my $result (@{ $top_level->{results} }) {
    print "$result->{id}\n";

Or you can just get values from all results elements for a particular key, say for id

my @ids = map { $_->{id} } @{ $top_level->{results} };
say "@ids";


1342 7062 432

Note that with nested structures, which contain references, you can also use syntax

$top_level->{results}[0]{domain};  # is ''  

The -> is optional between subscripts, see rule 3. in Using References in perlref.

When the hash keys are strings they should be quoted


However, a syntax shortcut allows us to omit quotes on barewords. But if there is anything other than a bareword inside {} it will be interpreted as an expression and evaluated. So if in any doubt use quotes. You want consistent notation throughout.

Resources: Tutorial perlreftut, reference perlref and data structures cookbook, perldsc.

A direct solution is given in stevieb's answer, creating a reverse lookup. Copied here for reference

my $results = $VAR1->{results};

my %by_ip = map {$_->{id} => $_} @$results;

print "$by_ip{1342}->{domain}\n";