我正在学习 Perl。我能够使用 Perl 哈希数据结构迭代 JSON 集合,例如这使用样本数据。但是,实际数据包含一些导致错误Not a HASH reference
或 的元素Can't use string ("...") as a HASH ref while "strict refs" in use
。
这是给我带来麻烦的有问题数据的简化示例:
{
"0y7vfr1234": {
"username": "[email protected]",
"password": "some-random-password123",
"uri": "ww1.example.com",
"index": 14
},
"v2rbz1568": {
"username": "[email protected]",
"password": "some-random-password125",
"uri": "ww3.example.com",
"index": 29
},
"active": "0y7vfr1234",
"0zjk1156": {
"username": "[email protected]",
"password": "some-random-password124",
"uri": "ww2.example.com",
"index": 38
},
"logging": {
"active": true
}
}
我只关心具有uri
.我想跳过其他的。我该怎么做呢?
在尝试了数十种不起作用的方法(并且只会导致新的或不同的错误)之后,以下是我最终解决这些错误的方法。但是,我认为有比使用ref()
.
#!/usr/bin/perl
use JSON;
use utf8;
use Data::Dumper;
use strict; use warnings;
my $data = '{
"0y7vfr1234": {
"username": "[email protected]",
"password": "some-random-password123",
"uri": "ww1.example.com",
"index": 14
},
"v2rbz1568": {
"username": "[email protected]",
"password": "some-random-password125",
"uri": "ww3.example.com",
"index": 29
},
"active": "0y7vfr1234",
"0zjk1156": {
"username": "[email protected]",
"password": "some-random-password124",
"uri": "ww2.example.com",
"index": 38
},
"logging": {
"active": true
}
}';
my $json = decode_json($data);
foreach my $key (keys %$json) {
if ( ref( $json->{$key} ) !~ m/HASH/ ) {
print "[" . ref( $json->{$key} ) . "]: skipping\n";
next;
}
if ( ! exists $json->{$key}->{uri} ) {
print "Not a server. It's type is: [" . ref($json->{$key}) . "]\n";
print "Without curly braces: $json->$key\n";
print Dumper($json->{$key});
print "With curly braces: $json->{$key}\n";
next;
}
print "checking $json->{$key}->{uri}\n";
# do some other stuff
}
代码或多或少按原样工作,但我对它不满意......或者我对它的理解。
我的问题是:
- 迭代像我的 JSON 这样的“混合”数据而不遇到错误的正确方法是什么?
- 显示有关我跳过的元素的一些信息的好方法是什么?我在代码中尝试了各种东西(数据转储器、不带大括号的打印等),但没有一个令人满意。有没有更好的方法可以显示有关跳过的内容的信息(当然不会导致错误)?
- 为什么上面的代码
$json->{$key}->{uri}
在没有箭头的情况下也能正常工作:$json->{$key}{uri}
?
我在 Linux 上使用 perl 5 版本 30。
答案1
像这样:
#!/usr/bin/perl
use JSON; use utf8;
use strict; use warnings;
my $data = '{
"0y7vfr1234": {
"username": "[email protected]",
"password": "some-random-password123",
"uri": "ww1.example.com",
"index": 14
},
"v2rbz1568": {
"username": "[email protected]",
"password": "some-random-password125",
"uri": "ww3.example.com",
"index": 29
},
"active": "0y7vfr1234",
"0zjk1156": {
"username": "[email protected]",
"password": "some-random-password124",
"uri": "ww2.example.com",
"index": 38
},
"logging": {
"active": true
}
}';
my $json = decode_json($data);
while (my ($key, $value) = each(%$json)) {
next unless ref $value; # skip if $value isn't a ref
next if scalar (keys %$value) < 2; # skip if the numbers of HASH keys < 2
print "$value->{uri}\n";
}