如何在Perl中解析3D JSON数组?

时间:2013-09-12 04:41:39

标签: perl hash multidimensional-array json

my $test = '{
   "name":"Tony",
   "body":[ {
             "arms":["hands:fingers", "muscles:biceps"],
             "stomach":["abs:sixpack", "noabs:onepack"]
             },
             {
             "arms":["fingers:nails", "knuckles:sharp"],
             "stomach":["abs:gut", "noabs:liquor"]
          }]
}';

我正在尝试这个并且它无法正常工作:

my $decoded = decode_json($test);
my @layer1 = @{ $decoded->{'body'} };
foreach ( @layer1 ) {
    @layer2 = $_->{$decoded->{'arms'} };
   foreach( @layer2 ) {
     print $_->{$decoded->{'hands'}} . "\n";
   }
}

我希望打印输出为:手指 我的最终结果目标是“如果abs是六包,那么将单词手指打印到文件中。”我当然试图从大型JSON大规模地做到这一点。

1 个答案:

答案 0 :(得分:1)

如果你打开了use strictuse warnings,那么你应该经常这样做,你会得到一堆关于未声明变量的致命错误。让我们先解决这些问题:

use strict;
use warnings;

use JSON;

my $test='{
   "name":"Tony",
   "body":[ {
             "arms":["hands:fingers", "muscles:biceps"],
             "stomach":["abs:sixpack", "noabs:onepack"]
             },
             {
             "arms":["fingers:nails", "knuckles:sharp"],
             "stomach":["abs:gut", "noabs:liquor"]
          }]
}';

my $decoded = decode_json($test);
my @layer1 = @{ $decoded->{'body'} };
foreach ( @layer1 ) {
   my @layer2 = $_->{$decoded->{'arms'} };
   foreach( @layer2 ) {
     print $_->{$decoded->{'hands'}} . "\n";
   }
}

现在,至少代码将在use strict下编译。但它会发出一堆警告:

Use of uninitialized value in hash element at js.pl line 21.
Use of uninitialized value in hash element at js.pl line 23.
Use of uninitialized value in concatenation (.) or string at js.pl line 23.

Use of uninitialized value in hash element at js.pl line 21.
Use of uninitialized value in hash element at js.pl line 23.
Use of uninitialized value in concatenation (.) or string at js.pl line 23.

这些警告是有用的信息!一个有用的工具use warnings

让我们看看第一个:在js.pl第21行的哈希元素中使用未初始化的值。

第21行是:

my @layer2 = $_->{$decoded->{'arms'} };

在此循环中,$_设置为外部数组的每个元素(@{ $decoded->{body} })。该数组的每个元素都是一个哈希引用。您正在做的是尝试使用散列的第一级中的键arms作为数组中元素指向的散列的键。那些哈希中不存在该键,这就是为什么你得到关于未初始化值的警告的原因。

为了得到我们想要的东西,我们只需要

my @layer2 = @{ $_->{arms} };

现在第三层更复杂;它是一个以冒号分隔的字符串数组,而不是哈希数组。在那个循环中,我们可以丢弃我们不想要的字符串,直到找到hands

foreach( @layer2 ) { 
    next unless /^hands:/;
    my ( $thing, $other_thing ) = split /:/, $_;
    print $other_thing, "\n";
}

这是固定脚本:

use strict;
use warnings;

use JSON;

my $test='{
   "name":"Tony",
   "body":[ {
             "arms":["hands:fingers", "muscles:biceps"],
             "stomach":["abs:sixpack", "noabs:onepack"]
             },
             {
             "arms":["fingers:nails", "knuckles:sharp"],
             "stomach":["abs:gut", "noabs:liquor"]
          }]
}';

my $decoded = decode_json($test);
my @layer1 = @{ $decoded->{'body'} };
foreach ( @layer1 ) {
    my @layer2 = @{ $_->{arms} };
    foreach( @layer2 ) {
        next unless /^hands:/;
        my ( $thing, $other_thing ) = split /:/, $_;
        print $other_thing, "\n";
    }
}

输出:

fingers

有关在Perl中使用复杂结构的更多信息,请参阅以下内容:

读取它们,再次读取它们,然后编写代码。然后再读一遍。