Reputation: 3
I'm reading a json file in perl and having trouble using the results.
I want to know how many views are present in the json file. there should be 2
my $data = decode_json($json);
print Dumper($data);
my @tmp=$data->{'views'};
my $nviews=scalar @tmp;
print "nviews : $nviews\n";
gives me
$VAR1 = {
'views' => [
{
'key' => 0,
'value' => {
'ptr_wrapper' => {
'data' => {
'width' => 776,
'height' => 1024,
'id_view' => 0,
'filename' => '000118800_15821618907.jpg',
'id_pose' => 0,
'id_intrinsic' => 13,
'local_path' => '/'
},
'id' => 2147483649
}
}
},
{
'key' => 1,
'value' => {
'ptr_wrapper' => {
'data' => {
'id_pose' => 1,
'id_intrinsic' => 11,
'filename' => '000132800_22050281512.jpg',
'id_view' => 1,
'local_path' => '/',
'width' => 850,
'height' => 1024
},
'id' => 2147483650
}
}
}
]
};
nviews : 1
thanks in advance for any help.luc
Upvotes: 0
Views: 3045
Reputation: 126722
When you write this
my $data = decode_json($json);
my @tmp = $data->{'views'};
you are creating a Perl array with a single element $tmp[0]
that is identical to $data->{'views'}
.
Your $data->{'views'}
is spot on, so you have correctly understood how to access the views
element of the hash referred to by your $data
variable, and as long as the hash key views
looks like a Perl identifier you can forget the quotes around it
But the values of Perl hashes and arrays are always scalar, so you must dereference them if you need to access the array, and the same applies to any substructures that you need to access
If you are dealing with complex data structures, it is usually best to keep a temporary scalar variable that tracks where you are within the structure. For instance, I would write
my $views = $data->{views};
Now I have a simple array reference to code with. I can dereference it to an array with @$views
, and I can access its elements with $views->[0]
etc.
Here's a rewrite of your own code that does what I have described. I have also used Data::Dump
to reformat the data that you show. It is generally far more concise and readable than the output from Data::Dumper
, but it isn't a core module so you will probably have to install it
I pull out $value->{ptr_wrapper}
as a lexical variable $wrapper
, and in turn $wrapper->{data}
as lexical variable $data
. The rest of the code becomes so much simpler, as I could otherwise be writing stuff like
say $data->{views}[0]{value}{ptr_wrapper}{data}{filename}
use strict;
use warnings 'all';
use feature 'say';
my $data = {
views => [
{
key => 0,
value => {
ptr_wrapper => {
data => {
filename => "000118800_15821618907.jpg",
height => 1024,
id_intrinsic => 13,
id_pose => 0,
id_view => 0,
local_path => "/",
width => 776,
},
id => 2147483649,
},
},
},
{
key => 1,
value => {
ptr_wrapper => {
data => {
filename => "000132800_22050281512.jpg",
height => 1024,
id_intrinsic => 11,
id_pose => 1,
id_view => 1,
local_path => "/",
width => 850,
},
id => 2147483650,
},
},
},
],
};
my $views = $data->{views};
my $nviews = scalar @$views;
print "nviews : $nviews\n\n";
for my $view ( @$views ) {
my $key = $view->{key};
my $value = $view->{value};
my $wrapper = $value->{ptr_wrapper};
my $data = $wrapper->{data};
say "key = $key";
say "ID = $wrapper->{id}";
say "filename = $data->{filename}";
say "height = $data->{height}";
say "width = $data->{width}";
print "\n";
}
nviews : 2
key = 0
ID = 2147483649
filename = 000118800_15821618907.jpg
height = 1024
width = 776
key = 1
ID = 2147483650
filename = 000132800_22050281512.jpg
height = 1024
width = 850
Upvotes: 4
Reputation: 17710
my $views = $data->{views};
my $nbViews = scalar @$views;
$data->{views}
is a reference to an array, not an array. Store the reference, and dereference it when needed.
Alternatively:
my @views = @{$data->{views}};
my $nbViews = scalar @views;
As pointed out by Borodin, note that this alternative makes a copy of the original array (potentially using a lot of memory). In some cases that may be what you actually want to do (if you need to modify it while leaving the original one intact, though note this would not be a deep copy), but most often (especially if you just want to count the items or iterate over them), you probably don't want to do that and just stick to keeping a reference (as in the first code snippet above).
Upvotes: 5