访问JSON解码为HASH和哈希引用数组

时间:2016-06-15 20:45:25

标签: json perl data-structures hash perl-data-structures

鉴于以下转储器输出是否有办法迭代每个哈希以仅列出每个results->id记录下的项目?我希望能够说出这样的话:

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

并将语句返回testing11.com作为结果。

我是否必须首先阅读所有results数组,然后使用$results[$counter]{id}访问其中的数据?我不知道该怎么办。

$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' => 'testing11.com',
                           'generated_timestamp' => 1546547669,
                           'id' => 1342
                          },
                         {
                           'priority' => 'Low',
                           'status' => 'Open',
                           'domain' => 'testing22.com',
                           'generated_timestamp' => 1464567669,
                           'id' => 7062
                          },
                         {
                           'priority' => 'Low',
                           'status' => 'Closed',
                           'domain' => 'testing33.com',
                           'generated_timestamp' => 1464267669,
                           'id' => 432
                          }]
      }

3 个答案:

答案 0 :(得分:4)

您的转储显示包含标量,两个hashref和一个arrayref的hashref。 arrayref具有元素的hashrefs。如果要从中检索特定元素,则需要知道索引。

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

迭代它取消引用数组

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

或者您可以从特定键的所有results元素中获取值,例如id

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

打印

1342 7062 432

请注意,对于包含引用的嵌套结构,您还可以使用语法

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

->在下标之间是可选的,请参阅Using References in perlref中的规则3.

当散列键是字符串时,应该引用它们

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

但是,语法快捷方式允许我们省略裸字的引号。但是如果在{}中除了单词之外还有其他内容,它将被解释为表达式并进行评估。因此,如果有任何疑问,请使用引号。你想要始终如一的符号。

资源:教程perlreftut,参考perlref和数据结构食谱,perldsc

stevieb的答案中给出了直接解决方案,创建了反向查找。复制在此以供参考

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

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

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

答案 1 :(得分:2)

您需要将内部$results数组转换为新的哈希:

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

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

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

输出:

testing11.com

这对@$results内的每个哈希引用做了什么,取id键的值,将其设置为新哈希(%modded)内的新键,以及然后将我们正在使用的整个哈希引用分配给该数字键的值。

答案 2 :(得分:1)

为了完整性,TIMTOWTDI-ness和-Ofun如果你使用最新的perl(use v5.24;),使用postfix dereferencing(默认启用),以及参考别名的实验支持(use feature 'refalias'; )然后您可以取消引用$VAR1并将其分配给别名(%data),然后您可以将其作为常规哈希访问:

use v5.24 ;
use feature 'refaliasing';

my $VAR1 = [AS ABOVE] ;
foreach \my %data ( $VAR1->{results}->@* ) { say $data{domain} };

我喜欢这种用法(尽管此时它远不是一个被接受的"成语")因为你调用解除引用语法"一次" - 后缀或传统形式 - 然后得到一个数据结构,其中不必在块内使用->

当然,您可以通过复制到临时哈希来完成此操作。但是别名可以被视为"更高效和可读性#34; ( cf。 Data::Alias)。

进一步参考