Читать структуру Perl JSON - PullRequest
       1

Читать структуру Perl JSON

0 голосов
/ 21 сентября 2018

Я получаю JSON из запроса:

use HTTP::Tiny;
my $response = HTTP::Tiny->new->get('https://jsonplaceholder.typicode.com/todos/1'); 
print "-------------------**------------------- \n";
my $content = $response->{content};
print $content->[0]->{name};

Ответ:

    [  
   {    
      "id": 1,
      "name": "Leanne Graham",    "username": "Bret",    "email": "Sincere@april.biz",
      "address": {
      "street": "Kulas Light",      "suite": "Apt. 556",
      "city": "Gwenborough",      "zipcode": "92998-3874",      "geo": {        "lat": "-37.3159",
      "lng": "81.1496"      }    },    "phone": "1-770-736-8031 x56442",    "website": "hildegard.org",
      "company": {
          "name": "Romaguera-Crona",
          "catchPhrase": "Multi-layered client-server neural-net",
          "bs": "harness real-time e-markets"
      }
  },
  {
      "id": 2,
      "name": "Ervin Howell",
      "username": "Antonette",
      "email": "Shanna@melissa.tv",
      "address": {
      "street": "Victor Plains",
      "suite": "Suite 879",
      "city": "Wisokyburgh",
      "zipcode": "90566-7771",
      "geo": {
          "lat": "-43.9509",
          "lng": "-34.4618"
      }
  }
]

Как прочитать каждое содержимое возвращаемой переменной json.Я пробовал это: print $content->[0]->{name};, но ничего не вернуть.

Как прочитать структуру JSON в Perl?

Ответы [ 2 ]

0 голосов
/ 21 сентября 2018

simbabque многое объяснил , и полезно иметь пример подкласса HTTP::Tiny.Я бы добавил следующее

  • Я считаю, что Cpanel::JSON::XS, несмотря на его запутанное имя, является лучшим модулем JSON в CPAN

  • В данных, возвращаемых с этого URL, нет элемента $content->[0]->{name}, хотя я думаю, это потому, что вы работаете над этим. Спасибо за размещение полезного источника данных: на вопросы гораздо приятнее отвечать

  • Очень важно проверить, действительно лиHTTP-запрос успешно завершен, и он умрет с объяснительным сообщением, если возникла проблема.Это просто дополнительное утверждение

    die $response->{reason} unless $response->{success};
    

Вот как бы я написал ваш код.Вместо того, чтобы выбирать поле, как вы, я использовал Data::Dump для отображения содержимого структуры

use strict;
use warnings 'all';

use HTTP::Tiny;
use Cpanel::JSON::XS 'decode_json';

my $response = HTTP::Tiny->new->get('https://jsonplaceholder.typicode.com/todos/1'); 

die $response->{reason} unless $response->{success};

my $data = decode_json $response->{content};

use Data::Dump;
dd $data;

output

{
  completed => bless(do{\(my $o = 0)}, "JSON::PP::Boolean"),
  id => 1,
  title => "delectus aut autem",
  userId => 1,
}

Как вы можете видеть, $content->[0]->{name} никогда не будет работать, потому что данные - это хеш , а не массив, и нигде нет ключа хеша name.Но латиница является сильным индикатором того, что сервер был обновлен с момента вашего вопроса, так что это не проблема

Значение $data->{completed} является логическим, и, вероятно, должно быть проверено с

if ( $data->{completed} ) { ... }

решить, что делать с ответом

0 голосов
/ 21 сентября 2018

Ваша переменная содержит строку , которая представляет структуру данных в формате JSON .Вам нужно преобразовать его в структуру данных Perl, чтобы использовать его в Perl.На данный момент это просто набор текста, и HTTP :: Tiny не заботится о том, какие данные он возвращает.

Core Perl приносит модуль JSON :: PP начиная с версии 5.13.9 (с выпуском 5.14) .

use strict;
use warnings;
use JSON::PP 'decode_json';
use Data::Printer;

my $json = qq({ "foo" : "bar" });

my $decoded = decode_json($json);
p $decoded;
print $decoded->{foo};

Будет выведено:

\ {
    foo   "bar"
}
bar

Если у вас более новый Perl и у вас есть другиеУстановленный материал, возможно, у вас также есть JSON :: MaybeXS , который выберет самый быстрый анализатор JSON, доступный автоматически.


Теперь, если вы хотите, чтобы ваш пользовательский агент знал, как это сделатьв нескольких местах вы можете легко создать подкласс.Я сделал элементарную реализацию здесь.Сохраните его в новом файле HTTP/Tiny/DecodeJSON.pm в нужной папке.Я бы поместил его в lib в каталоге вашего скрипта.

.
├── lib
│   └── HTTP
│       └── Tiny
│           └── DecodeJSON.pm
└── script.pl

Я бы также предложил добавить расширенную обработку ошибок.

package HTTP::Tiny::DecodeJSON;
use strict;
use warnings;
use JSON::PP 'decode_json';
use parent 'HTTP::Tiny';

# we need this to not throw a warning in HTTP::Tiny::_agent()    
use constant VERSION => '0.01';

sub get_json {
    my $self = shift;
    my $res = $self->get(@_);

    # add error handling here ...

    return decode_json $res->{content};
}

1;

Затем вы можете использовать его где угодно.Чтобы использовать его в своем скрипте, вам нужно добавить каталог lib в список каталогов, которые Perl ищет для своих модулей.

use strict;
use warnings;
use Data::Printer;

use lib 'lib';    
use HTTP::Tiny::DecodeJSON;

my $decoded = HTTP::Tiny::DecodeJSON->new->get_json(
    'https://jsonplaceholder.typicode.com/todos/1'
);
p $decoded;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...