UKR
UKR

Reputation: 93

parsing json file using perl

I am trying to parse a json file in perl. I want to extract the key "name" and corresponding value of it. my file looks like this

{
 "data":[
    {
        "name":"ABC",
        "id":"123",
    },
    {
        "name":"PQR",
        "id":"456",
    },
    {
        "name":"XYZ",
        "id":"789",
    }
]
}

I am trying with below code:

#/usr/lib/perl
use lib qw( ..);
use LWP::Simple;
use JSON;
my $filename = '/file.txt';
my $data;
if (open (my $json_str, $filename))
{
  local $/ = undef;
  my $json = JSON->new;
  $data = $json->decode(<$json_str>);
  close($json_stream);
}
print $data->{name};

But I not getting any output.

Can anyone tel me what is wrong ?

Upvotes: 7

Views: 78579

Answers (2)

wsdookadr
wsdookadr

Reputation: 2662

Your json file is invalid.

Lines 5,10,15 should not end with a comma since that is the last key/value pair of those hashes.

After you fix that, here is a version of your code that gives you the expected result:

#/usr/lib/perl
use strict;
use warnings;

use lib qw(..);

use JSON qw( );

my $filename = 'file.txt';

my $json_text = do {
   open(my $json_fh, "<:encoding(UTF-8)", $filename)
      or die("Can't open \"$filename\": $!\n");
   local $/;
   <$json_fh>
};

my $json = JSON->new;
my $data = $json->decode($json_text);

for ( @{$data->{data}} ) {
   print $_->{name}."\n";
}

Some of the problems:

  • You were using $json_stream and $json_str. You meant to use $json_stream in all places to denote the filehandle
  • The $data->{name} should be applied to all members of the array in the .json file, not to the json itself. So you need to iterate through them first

When debugging this, make sure your json is valid. Either through jsonlint.com or the json_xs utility that comes with JSON::XS from cpan.

JSON can describe complicated data structures so when you parse it into Perl you get a complex data structure too. Try to first have a look at the data structure using Data::Dumper or Data::Printer or Data::TreeDumper

Upvotes: 27

TLP
TLP

Reputation: 67900

Besides having an extra comma in the JSON string, you do not reference the right values. Always use

use strict; 
use warnings;

-- they will tell you what's wrong. In this case, you are printing an undefined value $data->{name}, a variable that has not been assigned a value. If you print your decoded structure in Data::Dumper it looks like this:

$VAR1 = {
          'data' => [
                      {
                        'name' => 'ABC',
                        'id' => '123'
                      },
                      {
                        'name' => 'PQR',
                        'id' => '456'
                      },
                      {
                        'name' => 'XYZ',
                        'id' => '789'
                      }
                    ]
        };

And as you can see, $data is actually a hash reference, where the first and only key is called 'data', whose value is an array with three elements, each containing a hash reference. So, in order to print those elements you would do something like:

print $data->{data}[0]{name};   # prints ABC

my $aref = $data->{data};
for my $element (@$aref) {
    print $element->{name};     # prints ABC, PQR, XYZ
}

Upvotes: 6

Related Questions