【问题标题】:Parse JSON using Perl使用 Perl 解析 JSON
【发布时间】:2019-03-21 15:54:47
【问题描述】:

我编写了一个测试脚本来执行某些功能。脚本按预期工作。目前,运行脚本所需的参数是使用Getopt::Long从命令行传递的。我想将命令行参数移动到 json 文件中。端点 ip 仍将作为命令行参数传递。 我希望端点 ip 充当密钥。例如,如果端点是 1.1.1.1,我想获取下面提到的 json 配置文件中端点 id 1.1.1.1 下列出的 client_ip、client_interface_ip、originip、....、端口。我该怎么做?

脚本的当前版本:

 use Getopt::Long;

     my ($self) = @_;

        GetOptions (
            "endpoint|e=s"           => \$self->{'endpoint'},
            "aggregator|a=s"         => \$self->{'aggregator'},
            "port|pt=s"              => \$self->{'port'},
            "client|c=s"             => \$self->{'client'},
            "client_interface|ci=s"  => \$self->{'client_interface'},
            "origin|o=s"             => \$self->{'origin'},
            "origin_interface|oi=s"  => \$self->{'origin_interface'},
            "interfacename|ot=s"     => \$self->{'i1'},
            "interfacename2|it=s"    => \$self->{'i2'},
             ) || $self->abort( "Invalid command line options.
                   Valid options are endpoint,aggregator,port,client,client_interface,
                     origin,origin_interface,outertunnel,innertunnel,");

       #Terminate the script execution if the reqd args are not passed
       my @required_args = qw(endpoint aggregator port client client_interface            origin origin_interface 
                              );

       for my $command_line_arguments (@required_args) {
         unless ($self->{$command_line_arguments}) {
          $self->abort('missing required argument ' . $command_line_arguments);
         }
       }

  $self->{'tObj'} =  QA::crypto::tunnels->new
      ('host'=> $self->{'endpoint'})
         or $self->abort('[Could not create a QA::Crypto::tunnels object.]');

参数的json文件:

{
        "Endpoints": [{

                "endpoint": "1.1.1.1",
                "client_ip": "3.4.5.6",
                "client_interface_ip": "10.11.12.14",
                "origin": "a.a.a.a",
                "origin_interface": "15.16.17.18",
                "interfacename": "name",
                "interfacename2": "name1",
                "sl": 19,
                "port": 362
        }, {

                "endpoint": "2.2.2.2",
                "client_ip": "19.20.21.22",
                "client_interface_ip": "23.24.25.26",
                "origin": "1.2.3.4",
                "origin_interface": "5.6.7.8",
                "interfacename": "interface name",
                "interfacename2": "interfacename_2",
                "sl": 19,
                "port": 366
        }]
}




#!/usr/bin/perl

use strict;
use warnings;
use JSON;

my $json;
{
   open my $fh, "<", "cfg.txt"
      or die("Can't open file \"cfg.json\": $!\n");
   local $/;
   $json = <$fh>;
}

my $data = decode_json($json);
$json = JSON->new->utf8->pretty->encode($data);

【问题讨论】:

    标签: perl perl-module


    【解决方案1】:

    第一个问题是关于 JSON 文件的合适设计。哈希在这里可以很好地发挥作用,而 arrayref 似乎根本不需要。端点值可以是键,它们的值是带有键相关信息的 hashref。如果您愿意,也可以将端点值保留在其 hashref 中。

    您的 JSON 中的密钥 "Endpoints" 似乎并没有发挥多大作用。但是,如果您确实需要它,也许因为会有其他类型的键,那么您可以为其值设置另一个 hashref,其中将包含以端点值作为键的 hashref。

    例如

    { “端点”:{ "1.1.1.1": { "client_ip": "3.4.5.6", ... }, "2.2.2.2": { "client_ip": "19.20.21.22", ... }, ... }, “其他键”:{ ... }, ... }

    最后一个值不应以逗号结尾。见JSON format

    当你把它引入 Perl 时,你会有嵌套的 hashrefs,比如

    $data = { 
        Endpoints => { 
             1.1.1.1 => { client_ip => '3.4.5.6',     ... }, 
             2.2.2.2 => { client_ip => '19.20.21.22', ... },
        }, 
        OtherKeys => { ... }, 
    };
    

    然后将值简单地检索为

    my $client_ip = $data->{Endpoints}{'1.1.1.1'}{client_ip};
    

    例如,检索所有端点并为它们列出client_ip

    my @endpoints = keys %{$data->{Endpoints}};
    foreach my $ip (@endpoints) {
        say $data->{Endpoints}{$ip}{client_ip};
    }
    

    Using References in perlrefthis post 完全是关于它的。另见perlreftutperldsc

    我们可以使用Data::Dumper检查(查看)整个数据结构

    use Data::Dumper;
    my $data = decode_json($json);
    print Dumper($data);
    

    还有许多其他用于处理嵌套数据结构的包。

    请注意JSON 包附带encode_json 和相关方法,因此您可以通过编程方式创建该文件。这可能有助于获得正确的格式并在未来进行维护。

    【讨论】:

    • 如果我想获取端点 1.1.1.1 的 client_ip,我该怎么做?
    • @nims 啊,对。添加到答案中。我也会添加一些处理 hashrefs 的参考。
    • @nims 我添加了一些用于处理 hashrefs 的参考资料,这是第一个用于此确切用途的参考资料。如果 hashref 业务有问题,请告诉我——这对于顺利使用 JSON 至关重要。
    • 我的 $json = '{ "Endpoints": { "198.18.193.126": { "client_ip": "3.4.5.6", "client_interface_ip": "9.1.1 .2", "origin “:“198.18 .193 .151”,“origin_interface”:“8.2 .0 .2”,“outertunnel”:“tunnel1”,“innertunnel”:“innertunnel”,“slot”:1900,“port”:362 } , }';我的 $j = JSON-> 新的;我的 $data = $j->decode($json);我的 $ 客户; $client = $data->{Endpoints}{198.18.193.126}{client_ip};打印 $client;
    • 我无法打印 $client = $data->{Endpoints}{198.18.193.126}{client_ip} 中的值;为什么会这样?
    猜你喜欢
    • 1970-01-01
    • 2013-03-17
    • 2013-03-11
    • 2011-06-30
    • 2012-04-12
    • 2018-02-07
    • 2014-02-08
    • 1970-01-01
    • 2011-07-09
    相关资源
    最近更新 更多