读取Perl JSON结构

时间:2018-09-21 10:11:09

标签: json perl

我从请求中获取了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}; ,但什么也不返回。

如何阅读perl的JSON结构?

2 个答案:

答案 0 :(得分:4)

您的变量包含一个字符串,该字符串表示JSON format中的数据结构。您需要将其转换为Perl数据结构,以便在Perl中使用遍历。此时,这只是一堆文本,HTTP :: Tiny不在乎它返回哪种数据。

Core Perl带来了JSON::PP模块starting from version 5.13.9 (with the 5.14 release)

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;

答案 1 :(得分:1)

simbabque has explained a lot, 举一个子类HTTP::Tiny的例子很有用。我会添加以下内容

  • 我相信Cpanel::JSON::XS尽管名称复杂,但却是CPAN上的高级JSON模块

  • 从该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;

输出

{
  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} ) { ... }

决定如何处理响应