【问题标题】:Parsing JSON data in Perl在 Perl 中解析 JSON 数据
【发布时间】:2020-02-07 03:49:44
【问题描述】:

我正在解析 .json 文件中的 JSON 数据。这里我有 2 种格式的 JSON 数据文件。

我可以解析第一个 JSON 文件 - 文件如下所示:

file1.json

{
  "sequence" : [ {
    "type" : "type_value",
     "attribute" : {
      "att1" : "att1_val",
      "att2" : "att2_val",
      "att3" : "att3_val",
      "att_id" : "1"
    }
  } ],
  "current" : 0,
  "next" : 1
}

这是我的脚本:

#/usr/lib/perl
use strict;
use warnings;
use Data::Dumper;

use JSON;

my $filename = $ARGV[0]; #Pass json file as an argument
print "FILE:$filename\n";

my $json_text = do {
   open(my $json_fh, "<:encoding(UTF-8)", $filename)
      or die("Can't open \$filename\": $!\n");
   local $/;
   <$json_fh>
};

my $json = JSON->new;
my $data = $json->decode($json_text);

my $aref = $data->{sequence};

my %Hash;

for my $element (@$aref) {
    my $a = $element->{attribute};
    next if(!$a);

    my $aNo = $a->{att_id};
    $Hash{$aNo}{'att1'}     = $a->{att1};
    $Hash{$aNo}{'att2'}     = $a->{att2};
    $Hash{$aNo}{'att3'}     = $a->{att3};
}

print Dumper \%Hash;

所有内容都存储在 %Hash 中,当我打印 %Hash 的 Dumper 时,我得到以下结果。

$VAR1 = {
          '1' => {
                   'att1' => 'att1_val',
                   'att2' => 'att2_val',
                   'att3' => 'att3_val'
                 }
        };

但是当我解析第二组 JSON 文件时,我使用上面的脚本得到了空哈希。 输出:

$VAR1 = {};

这是 JSON 文件 - file2.json

{
  "sequence" : [ {
    "type" : "loop",
    "quantity" : 8,
    "currentIteration" : 0,
    "sequence" : [ {
      "type" : "type_value",
      "attribute" : {
        "att1" : "att1_val",
        "att2" : "att2_val",
        "att3" : "att3_val",
        "att_id" : "1"
      }
    } ]
  } ]
}

我们可以在上面的 JSON 数据文件中看到两个sequence,这是导致问题的原因。 有人可以告诉我脚本中缺少什么以便解析file2.json

【问题讨论】:

  • 它已经被“解析”过了。直接看JSON解码的结果。问题在于稍后在代码中访问它。代码还需要“查看”内部序列作为数组
  • 是的。如何访问内部序列。
  • "sequence" 数组内部可以有超过 1 个元素吗?

标签: json perl


【解决方案1】:

一种可能是检查type 字段以区分两种文件格式:

# [...]
for my $element (@$aref) {
    if ( $element->{type} eq "loop" ) {
        my $aref2 = $element->{sequence};
        for my $element2 ( @$aref2 ) {
            get_attrs( $element2, \%Hash );
        }
    }
    else {
        get_attrs( $element, \%Hash );
    }
}

sub get_attrs {
    my ( $element, $hash ) = @_;

    my $a = $element->{attribute};
    return if(!$a);

    my $aNo = $a->{att_id};
    $hash->{$aNo}{'att1'}     = $a->{att1};
    $hash->{$aNo}{'att2'}     = $a->{att2};
    $hash->{$aNo}{'att3'}     = $a->{att3};
}

【讨论】:

    【解决方案2】:

    如果符合您的要求,请查看以下代码

    #!/usr/bin/env perl
    #
    # vim: ai:sw=4:ts=4
    #
    
    use strict;
    use warnings;
    use feature 'say';
    
    use Data::Dumper;
    use JSON;
    
    my $debug = 0;          # debug flag
    
    my $filename = shift;   # Pass json file as an argument
    
    say "FILE: $filename";
    
    open(my $json_fh, "<:encoding(UTF-8)", $filename)
        or die("Can't open \$filename\": $!\n");
    
    my $json_data = do { local $/; <$json_fh> };
    
    close $json_fh;
    
    my $json = JSON->new;
    my $data = $json->decode($json_data);
    
    say Dumper($data) if $debug;
    
    my $data_ref;
    my %Hash;
    
    $data_ref = $data->{sequence}[0]{attribute}
                if $filename eq 'file1.json';
    $data_ref = $data->{sequence}[0]{sequence}[0]{attribute}
                if $filename eq 'file2.json';
    
    say Dumper($data_ref) if $debug;
    
    my @fields = qw/att1 att2 att3/;
    my $aNo = $data_ref->{att_id};
    my %data_hash;
    
    @data_hash{@fields} = $data_ref->{@fields};
    $Hash{$aNo} = \%data_hash;
    
    say Dumper(\%Hash);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-12-05
      • 2013-07-08
      • 2013-09-16
      • 2012-04-12
      • 1970-01-01
      • 1970-01-01
      • 2019-05-07
      相关资源
      最近更新 更多