Reputation: 553
I am new to perl and i had written below snippet of code to get the JSON objects from the data. But the input data has both hashes and arrays, So how do i get those values for "id" which is an array ?
use strict;
use warnings;
use Data::Dumper;
use JSON
my $data = '{"total":325,"id": [78,234,737,1253,1459,1733,2166,2653,2855,3133,3414,3538,3729,3905,3991,4110,4160,4536,4692,4701]}';
print Dumper($data);
my @hash_ref = from_json($data);
foreach my $hash_scalar (@hash_ref) {
foreach (keys %{$hash_scalar}) {
print "$_ => ${$hash_scalar}{$_}\n";
}
}
Output Getting
#$VAR1 = '{"total":325,"id":
[78,234,737,1253,1459,1733,2166,2653,2855,3133,3414,3538,3729,3905,3991,4110,4160,4536,4692,4701]}';
id => ARRAY(0x2afee4c)
total => 325
Upvotes: 1
Views: 5704
Reputation: 6798
Perhaps following code will cover your question in more complete extent.
NOTE: I've added a hash in data block as bonus
use strict;
use warnings;
use feature 'say';
use JSON;
use Data::Dumper;
my $debug = 0;
my $data = '{ "total":325,
"id": [78,234,737,1253,1459,1733,2166,2653,2855,3133,3414,3538,3729,3905,3991,4110,4160,4536,4692,4701],
"person": {
"first": "John",
"last": "Smith",
"age": 27,
"occupation": "accountant",
"wife": "Maria Smith",
"son": "Alex Smith",
"daughter": "Samantha Smith",
"dog": "Sparky",
"hobby": "photography"
}
}';
say Dumper($data) if $debug;
my $json = from_json($data);
say Dumper($json) if $debug;
while( my($k,$v) = each %{$json} ) {
say "Key: $k";
if( ref $v eq 'ARRAY' ) {
say "\tValue is ARRAY";
for ( @{$v} ) { say "\t\t[$_]" }
} elsif( ref $v eq 'HASH' ) {
say "\tValue is HASH";
while( my($hk,$hv) = each %{$v} ) {
say "\t\t$hk => $hv";
}
} else {
say "\tValue: $v";
}
}
say '-' x 40;
say 'Element with index 5 is ' . $json->{id}[5];
say 'Name of the son is ' . $json->{person}{son};
say 'Name of the daughter is ' . $json->{person}{daughter};
Output
Key: person
Value is HASH
son => Alex Smith
occupation => accountant
daughter => Samantha Smith
age => 27
wife => Maria Smith
dog => Sparky
last => Smith
first => John
hobby => photography
Key: id
Value is ARRAY
[78]
[234]
[737]
[1253]
[1459]
[1733]
[2166]
[2653]
[2855]
[3133]
[3414]
[3538]
[3729]
[3905]
[3991]
[4110]
[4160]
[4536]
[4692]
[4701]
Key: total
Value: 325
----------------------------------------
Element with index 5 is 1733
Name of the son is Alex Smith
Name of the daughter is Samantha Smith
Upvotes: -1
Reputation: 132822
The id
is a key in the hash reference you get back, and you want to grab its value, which is an array reference. You can either keep that as a reference or grab its elements right away:
#!perl
use v5.24;
use JSON qw(from_json);
my $data = '{"total":325,"id": [78,234,737]}';
my $json = from_json($data);
# get the hash key to get the hash value, which is an array reference
my $ids_array_ref = $json->{id};
# OR, use the postfix dereference to get the ids as a normal list
my @ids_array = $json->{id}->@*;
# OR, use the older circumfix notation (before Perl v5.24). These are all
# the same:
my @ids_array = @{ $json->{id} };
my @ids_array = @{ $ids_array_ref };
my @ids_array = @$ids_array_ref;
For example:
#!perl
use v5.24;
use JSON qw(from_json);
my $data = '{"total":325,"id": [78,234,737]}';
my $json = from_json($data);
foreach my $id ( $json->{id}->@* ) {
say "Got id $id";
}
This outputs:
Got id 78
Got id 234
Got id 737
But, you have to handle the other hash value types too. To decide how to print something, you have to check if it's a reference and what sort of reference it is (I ignore the other sorts here):
#!perl
use v5.24;
use JSON qw(from_json);
my $data = '{"total":325,"id": [78,234,737]}';
my $json = from_json($data);
foreach my $key ( keys $json->%* ) {
print "$key: ";
if( ref $json->{$key} eq 'ARRAY' ) {
say join ' ', $json->{$key}->@*;
}
elsif( ref $json->{$key} ) { # all other reference types
warn "I don't handle this yet"
}
else {
say $json->{$key};
}
}
But, you might have deeper levels of nesting, so you'd need to think about that too if you want to output everything. If I know what keys I want, I don't try to go through everything in a general way. I go directly to want I want:
#!perl
use v5.24;
use JSON qw(from_json);
my $data = '{"total":325,"id": [78,234,737]}';
my $json = from_json($data);
say "id: ", join ' ', $json->{id}->@*;
say "total: ", $json->{total};
Your original code was doubly complicated. The result of from_json
is the reference that represents the JSON data structure. That's a JSON object, which is what Perl calls a hash, so you get a hash reference back.
my $hash_ref = from_json( $data );
Your example almost worked because you got an array of one element, which is that hash reference. The other foreach
then iterates over that one element. Get rid of that outer array and you get rid of the outer loop.
We cover references and data structures in Intermediate Perl, although the perldsc is good too. We have a long examples of deeply-nested and recursive data structures.
If you're new, you may want to start with Learning Perl, though.
Upvotes: 2
Reputation: 434
My Perl is getting rusty, but I think something like this should do the trick. You need to de-reference your array reference with another @{...}
like @{${$hash_scalar}{$_}}
.
use strict;
use warnings;
use Data::Dumper;
use JSON
my $data = '{"total":325,"id": [78,234,737,1253,1459,1733,2166,2653,2855,3133,3414,3538,3729,3905,3991,4110,4160,4536,4692,4701]}';
print Dumper($data);
my @hash_ref = from_json($data);
for my $hash_scalar (@hash_ref) {
for my $key (keys(%{$hash_scalar})) {
print("$key => @{${$hash_scalar}{$_}}\n");
}
}
Upvotes: 0