I'm learning Perl. I am able to iterate over a JSON collection using a Perl hash data structure like this using sample data. However, the actual data contains some elements that are causing either the error Not a HASH reference or Can't use string ("...") as a HASH ref while "strict refs" in use.
Here's a simplified example of problematic data that is giving me trouble:
{
"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
}
}
I am only concerned with the data elements that have a uri. I want to skip over the others. How would I do that?
After trying dozens of things that did not work (and only led to new or different errors), here is how I finally got around the errors. However, I assume there is a much better way to do it than using 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
}
The code more or less works as is, but I'm not happy with it... or my understanding of it.
My questions are:
- What is the right way to iterate over "mixed" data like my JSON without encountering errors?
- What is a good way to display some information about the elements that I skip? I tried various things in the code (Data Dumper, printing without curly braces, etc.) and none of them are satisfactory. Is there a better way I can show information about what was skipped (without causing an error, of course)?
- Why does the above code
$json->{$key}->{uri}also work without the arrow like this:$json->{$key}{uri}?
I'm using perl 5, version 30 on Linux.
refis OK. You can also usereftypefromScalar::Utilfor blessed references. 2. useData::Dumperor write your own, better variant. 3. because TIMTOWTDI. All of$a->{b}->{c},$$a{b}{c},$a->{b}{c},$$a{b}->{c}mean exactly the same. 4. better ask such questions on stackoverflow