读取Perl JSON结构

读取Perl JSON结构,json,perl,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}; 答

我从请求中获取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结构?

您的变量包含一个字符串,该字符串表示perl中的数据结构。您需要将其转换为Perl数据结构,以便在Perl中使用traverse。在这一点上,它只是一堆文本,HTTP::Tiny并不关心它返回的数据类型

核心Perl带来了这个模块

这将输出:

\ {
    foo   "bar"
}
bar
如果您已经安装了较新的Perl并安装了一些其他东西,那么您可能也安装了,这将自动选择最快的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;
,, 有一个子类化的例子很有用。我想补充以下几点

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

  • 从该URL返回的数据中没有
    $content->[0]->{name}
    元素,尽管我认为这是因为您正在处理它感谢您发布了一个可用的数据源:它让问题回答起来更加愉快

  • 检查HTTP请求是否成功是非常重要的,如果出现问题,则会显示一条解释性消息。这只是一个额外的声明

    die $response->{reason} unless $response->{success};
    
下面是我将如何编写您的代码。我没有像您那样选择字段,而是使用了 显示结构的内容

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;
输出 如您所见,
$content->[0]->{name}
永远不会工作,因为数据是散列而不是数组,并且任何地方都没有散列键
name
。但拉丁语是一个强有力的指示器,表明服务器在您提出问题后已经更新,所以这不是问题

$data->{completed}
是布尔值,可能需要使用

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

要决定如何处理回复

您必须向我们展示内容中的内容。它只是纯文本、未编码的JSON吗?如果您打印该变量会发生什么情况?我已经更新了代码以打印结果我已经更新了答案以显示如何构建自己的HTTP::Tiny子类。这是一个不错的答案,但我担心您的子类化示例可能会被逐字复制而不被理解。这是一种有效的技术,但也许最好将模块作为一个单独的
.pm
文件编写,而不是仅仅推荐它,因为我发现源文件中的多个
声明是一个常见的混淆源。“为什么没有
使用HTTP::Tiny::DecodeJSON
”是最常见的一种,人们尝试做同样的事情往往会失败,因为他们对pragmas的范围缺乏了解。@Borodin如何?这很好。我可能会抱怨
Data::Printer
没有生成可执行的Perl,在IDE中或者当
STDOUT
被定向到一个文件时没有用,但这与此无关!我从来不知道是否需要告诉人们如何“在
@INC
目录中创建一个名为
HTTP/Tiny/DecodeJSON.pm
的文件”,但你的解释非常清楚。请不要认为你必须同意我提出的任何批评:我不是预言家,它们是另一种观点。@Borodin我只在同意批评或改进建议时才同意。我不同意你不喜欢Data::Printer,所以我很乐意继续使用它。:)那很好。不管怎么说,我是个守旧的人,命令窗口中的彩色文本看起来比应该的更奇怪。我可以考虑一些类似于<代码>使用的if -t STDIN,“数据::打印机”/CODE(但<代码> P<代码>需要适当的别名),否则你将看到VT52转义序列,它们没有意义。您真的是从命令行运行所有的东西吗,而不是从允许您运行正在使用的代码的IDE或编辑器?Cpanel::JSON::XS是CPAN上速度最快、错误最少的JSON模块,是的,它是前面提到的JSON::MaybeXS使用的默认模块。@Grinnz:当然,但是
JSON::MaybeXS
将仅从已安装的模块中选择。由于它不是以
JSON
开头,因此
Cpanel::JSON::XS
经常被忽略,不太可能可用。除非请求纯perl安装,否则它会作为依赖项被引入。
{
  completed => bless(do{\(my $o = 0)}, "JSON::PP::Boolean"),
  id => 1,
  title => "delectus aut autem",
  userId => 1,
}
if ( $data->{completed} ) { ... }