2013-03-27 8 views
4

Я пытаюсь разобрать json-файл в perl. Я хочу извлечь ключ «имя» и соответствующее ему значение. мой файл выглядит следующим образомparsing json file using perl

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

Я пытаюсь с ниже код:

#/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}; 

Но я не получаю никакого вывода.

Может ли кто-нибудь сообщить мне, что не так?

+0

http://jsonlint.com/ использовать эту страницу, чтобы подтвердить или JSON – Zelldon

ответ

18

Ваш json-файл недействителен.

Линии 5,10,15 не должны заканчиваться запятой, так как это последняя пара ключей/значений этих хэшей.

После устранения этого, здесь есть версия кода, который дает ожидаемый результат:

#/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"; 
} 

Некоторые из проблем:

  • Вы использовали $json_stream и $json_str. Вы должны использовать $json_stream во всех местах, чтобы обозначить дескриптор файла
  • $data->{name} должен применяться ко всем членам массива в файле .json, а не к самому json. Таким образом, вам необходимо сначала прокручивать их.

При отладке убедитесь, что ваш json действителен. Либо через jsonlint.com, либо утилиту json_xs, которая поставляется с JSON::XS из cpan.

JSON может описывать сложные структуры данных, поэтому, когда вы анализируете его на Perl, вы также получаете сложную структуру данных. Попробуйте сначала взглянуть на структуру данных с использованием Data::Dumper или Data::Printer или Data::TreeDumper

+0

ли не ваш 'делать открытым (...)' утечка открытый файл? – EdMaster

+1

[filehandle закрыт] (http://stackoverflow.com/a/953885/827519), когда он [выходит за рамки] (http://www.perlmonks.org/?node_id=287647#287686). – average

4

Помимо того, что лишняя запятая в строке JSON, вы не ссылаться на правильные значения. Всегда используйте

use strict; 
use warnings; 

- они расскажут вам, что не так. В этом случае вы печатаете неопределенное значение $data->{name}, переменную, которой не присвоено значение. Если распечатать декодированную структуру в Data::Dumper это выглядит следующим образом:

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

И как вы можете видеть, $data на самом деле хэш ссылка, где первый и единственный ключ называется 'data', значение которого представляет собой массив с три элементы, каждая из которых содержит хеш-ссылку. Итак, для того, чтобы напечатать те элементы, которые вы бы сделать что-то вроде:

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

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

Можно ли это сделать более кратко, без цикла? – Geremia

+0

Вот альтернатива 'map {print $ _-> {name}; } @ {$ data -> {data}}; '.Или вы можете 'print join (", ", (map {$ _-> {name}} @ {$ data -> {data}});' Это все еще цикл. Почему требуется решение без петли? – average