我从请求中获取了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结构?
答案 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} ) { ... }
决定如何处理响应