在Perl中获取JSON

时间:2016-04-22 21:23:51

标签: json perl http get mojolicious

我一直在使用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");

上面的网址是那些不起作用的网址,但如果我将其更改为:

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 ......

3 个答案:

答案 0 :(得分:4)

用户代理主要用于通过http下载文件。通常不期望它们处理文件系统URI。您需要自己openread the file,或使用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;
}

答案 1 :(得分:2)

我自己使用WWW::Mechanize执行所有此类任务。来自doc:

  

WWW :: Mechanize是LWP :: UserAgent的合适子类,您也可以   使用任何LWP :: UserAgent的方法。

这意味着您也可以使用file://类型的网址提供。

例如,以下单行转储您的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;

答案 2 :(得分:1)

总是要说明您正在使用的其他模块,这一点非常重要。我认为您的代码使用Method::Signatures,并且我已经测试了下面的代码,只是检查它是否与该模块一起编译

Mojolicious 是一个出色的工具,但它专注于HTTP URL。 LWP::UserAgent更通用,documentation for LWP说明了这个

  

提供HTTP样式通信的面向对象模型。在此框架内,我们目前支持访问http,https,gopher,ftp,新闻,文件和mailto资源

你的方法就像这样。它没有经过测试

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完全不同的变量)也无法阻止您使用