在 Perl 中获取 JSON

Fetching JSON in Perl

我一直在用 Perl 构建模拟器,我面临的问题之一是解析计算机中的 JSON 文件。当我尝试从我的服务器获取它们时,它们工作正常...

    method getContent(\@arrURLS) {
    my %arrInfo;
    my $resUserAgent = Mojo::UserAgent->new;
    foreach my $strURL (@arrURLS) {
        $resUserAgent->get($strURL => sub {
            my($resUserAgent, $tx) = @_;
            if ($tx->success) {
                my $strName = basename($strURL, '.json');
                my $arrData = $tx->res->body;
                $arrInfo{$strName} = $arrData;
            }
            Mojo::IOLoop->stop;
        });
        Mojo::IOLoop->start;
    }
    return \%arrInfo;
}

我们假设 @arrURLS 是:

my @arrURLS = ("file:///C:/Users/Test/Desktop/JSONS/first.json", "file:///C:/Users/Test/Desktop/JSONS/second.json");

上面的 url 是行不通的,但是如果我将其更改为:

my @arrURLS = ("http://127.0.0.1/test/json/first.json", "http://127.0.0.1/test/json/second.json");

有效。

另外我想使用比 Mojo::UserAgent 更好的东西,因为它看起来有点慢,当我使用 CoroLWP::Simple 时它要快得多但不幸的是 Coro 在 Perl 5.22 中被破坏...

User Agent主要是通过http下载文件。通常不希望它们处理文件系统 URI。您需要 open and read the file yourself, or use a module like File::Slurp 为您完成。

它可能看起来像这样。

use File::Slurp 'read_file';

method getContent(\@arrURLS) {
    my %arrInfo;
    my $resUserAgent = Mojo::UserAgent->new;
    foreach my $strURL (@arrURLS) {
        if (substr($strURL, 0, 4) eq 'file') {
            $arrInfo{basename($strURL, '.json')} = read_file($strURL);
        } else {
            $resUserAgent->get($strURL => sub {
                my($resUserAgent, $tx) = @_;
                if ($tx->success) {
                    my $strName = basename($strURL, '.json');
                    my $arrData = $tx->res->body;
                    $arrInfo{$strName} = $arrData;
                }
                Mojo::IOLoop->stop;
            });
            Mojo::IOLoop->start;
        }
    }
    return \%arrInfo;
}

我自己使用 WWW::Mechanize 完成所有此类任务。来自文档:

WWW::Mechanize is a proper subclass of LWP::UserAgent and you can also use any of LWP::UserAgent's methods.

这意味着您也可以使用 file:// 类型的 URL 来提供它。

例如,以下一行转储您的 passwd 文件。

perl -MWWW::Mechanize -E 'say WWW::Mechanize->new->get("file://etc/passwd")->content'

或者没有任何错误处理的例子...

use 5.014;
use warnings;
use WWW::Mechanize;
my $mech = WWW::Mechanize->new;
$mech->get('file://some/path');
say $mech->content;

无论如何,对本地文件使用一些 file-based 实用程序可能更好,我自己对所有文件使用 Path::Tiny 模块,它具有(不仅限于)文件 slurping 方法,例如:

use Path::Tiny;
my $content = path('/some/path')->slurp;

或者只是简单的 perl:

open my $fh, '<', '/some/file' or die "...";
my $content = do { local $/; <$fh> };
close $fh;

请务必说明您正在使用哪些附加模块。我认为您的代码使用 Method::Signatures,并且我测试了下面的代码只是为了检查它是否使用该模块进行编译

Mojolicious 是一款出色的工具,但它专注于 HTTP URL。 LWP::UserAgent is much more general-purpose, and the documentation for LWP 这么说

Provides an object oriented model of HTTP-style communication. Within this framework we currently support access to http, https, gopher, ftp, news, file, and mailto resources

你的方法变成了这样。未经测试

method get_content(\@urls) {

    my %info;

    my $ua = LWP::UserAgent->new;
 
    for my $url (@urls) {

        my $res = $ua->get($url);
        die $res->status_line unless $res->is_success;

        my $name     = basename($url) . '.json';
        my $data     = $res->decoded_content;
        $info{$name} = $data;
    }

    \%info;
}


我还鼓励您在 Perl 代码的上下文中放弃匈牙利符号,因为该语言已经具有表示数据类型的标志

@arrURLS 复制了这个 arrURLS 是一个数组的信息,而 %arrInfo 是错误的,因为这个 arrInfo 是一个 哈希 $arrData 实际上是一个 标量 ,尽管也许一些指示它也是 参考 的指标可能会有所帮助,而 $arrURLS[0] 是也是一个 标量(因此是美元)

也没有什么可以阻止您使用 $arrURLS(这是一个完全独立于 @arrURLS 的变量)