bdi*_*zle 4 perl hash json hash-of-hashes
我有一个json结构,我正在解码,看起来像这样:
person => {
city => "Chicago",
id => 123,
name => "Joe Smith",
pets => {
cats => [
{ age => 6, name => "cat1", type => "siamese", weight => "10 kilos" },
{ age => 10, name => "cat2", type => "siamese", weight => "13 kilos" },
],
dogs => [
{ age => 7, name => "dog1", type => "siamese", weight => "20 kilos" },
{ age => 5, name => "dog2", type => "siamese", weight => "15 kilos" },
],
},
},
}
Run Code Online (Sandbox Code Playgroud)
我能打印city,id,name这样做:
foreach my $listing ($decoded->{person})
{
my $city = $listing->{city};
my $name = $listing->{name};
name - $city - \n";
}
Run Code Online (Sandbox Code Playgroud)
但是,我不确定如何打印pets->cats或pets->dogs.我可以通过以下方式转储它们:
my @pets = $listing->{pets}->{cats};
dump @pets;
Run Code Online (Sandbox Code Playgroud)
但我不确定如何通过哈希结构访问它们.
假设你$listing是一个人,你必须取消引用数组和散列引用.
# as long as we are assuming $listing is a person
# this goes inside the foreach you posted in your
# question.
# this will print all cats' names
foreach my $cat ( @{ $listing->{pets}->{cats} } )
{
# here $cat is a hash reference
say $cat->{name}; # cat's name
}
Run Code Online (Sandbox Code Playgroud)
等等其他东西.
要从结构中访问它们,您可以执行以下操作:
say $listing->{pets}->{cats}->[0]->{name}; # this will print 'cat1'
Run Code Online (Sandbox Code Playgroud)
一旦你了解规则,挖掘到一个大的结构是非常简单的:
{}[]->在第一个标识符之前使用.->)是可选的.所以:*$data->{person}{name}return 'Joe Smith'
*$data->{person}->{name}也返回'Joe Smith'
*$data->{pets}{cats}[0]{age}返回6.
有关此主题的更多详细信息,请参阅Perl数据结构手册(perldoc perldsc)
当你使用像这样的大型结构时,有一些重要的事情需要注意.其中最大的是autovivification.Autoviv意味着Perl会自动生成数据结构元素,让您的生活更轻松.不幸的是,它也会让事情变得困难.
例如,当我这样做时,autoviv很棒:
my $data;
$data->{horse}[0]{color} = 'brown';
Run Code Online (Sandbox Code Playgroud)
Autoviv神奇地变成$data了一个hashref,它包含horse一个以数组ref作为其值的键.数组引用由散列引用填充.最后的散列引用然后得到键值对color => brown.
当你走一个结构并对存在进行深入测试时,问题就出现了:
# Code from above continues:
if( exists $data->{cat}[5]{color} ) {
print "Cat 5 has a color\n";
}
use Data::Dumper;
print Dumper $data;
Run Code Online (Sandbox Code Playgroud)
在这里,autovivification通过在数据中创建一堆垃圾来焚烧你,这是程序输出:
$ VAR1 = {'cat'=> [undef,undef,undef,undef,undef,{}],'horse'=> [{'color'=>'brown'}]};
现在你可以通过仔细测试你的结构的每一层存在来防止这种事情,但这对屁股来说是一个巨大的痛苦.相反,我更喜欢使用Data :: Diver.
use Data::Diver qw( Dive );
my $dog_20_color = Dive( $data, 'dog', 20, 'color' );
print "Dog 20 is $dog_20_color\n" if defined $dog_20_color;
Run Code Online (Sandbox Code Playgroud)
$data 在这里没有改变.
此外,您可能已经注意到,由于Dive获取了一个键或索引列表,这意味着它易于以编程方式构建键/索引列表并在代码中下降任意路径.
Data :: Diver可以成为一个真正的生命保护程序,当你必须对大而不稳定的数据结构进行大量操作时.
| 归档时间: |
|
| 查看次数: |
19497 次 |
| 最近记录: |