perl

时间:2015-12-16 02:06:41

标签: json perl

具有如下所示的JSON结构:

{"gene_res":{"gene":[{"gname":{"variant":[{"annotation":"","an":2}]}}]}}

我的代码:

use warnings; 
use diagnostics; 
use strict; 
 use JSON::MaybeXS; 
     if ($#ARGV!=0){
    warn "ERROR: Expecting a JSON file as input\n";
    exit;
    }

  my ($INFILE)=@ARGV;
  my $json;

 {
    local $/; #Enable 'slurp' mode
    open my $IFH, "<", "$INFILE";
    $json= <$IFH>;
    close $IFH;
 }


printingMeta($json);

sub printingMeta
 {
    my $hash = decode_json($_[0]);
    my $gene='';

    foreach my $arrayref (@{$hash->{gene_res}->{gene}})
    {
            foreach my $gene (keys %{$arrayref})
            {
                    print "$gene\n";
                    #This works, I get "name"


            }

    }

我无法找到达到/注释的方法。 在上面的例子中,gname是一个数组,所以我可以有很多“gnames”,有很多diff值。 我需要这样的东西:

foreach my $item (@{$hash->{gene_res}{$gene}{variant}})

但这不起作用。获取错误不是......的

的HASH引用

3 个答案:

答案 0 :(得分:3)

@{ $hash->{gene_res}{$gene_name}{variant} }

是错误的,因为图层是数组,而不是哈希。它需要

@{ $hash->{gene_res}[$gene_idx]{$gene_name}{variant} }

数据结构相当奇怪,所以你在缠绕它时遇到问题并不奇怪。

所以,

sub printingMeta {
    my ($data) = @_;
    for my $genes (@{ $data->{gene_res}->{gene} }) {
        for my $gene_name (keys(%$genes)) {
            print($gene_name, "\n");
            my $gene = $genes->{$gene_name};
            for my $variant (@{ $gene->{variant} }) {
                ...
            }
        }
    }
}

其他程序清理完毕:

use strict; 
use warnings; 

use JSON qw( decode_json );

die("usage: $0 json_file\n")
    if @ARGV != 1;

my $json; { local $/; $json = <>; }
my $data = decode_json($json);
printingMeta($data);

答案 1 :(得分:2)

我不确定您是否正确理解数据结构。使用Data::Dumper打印出数据结构是了解结构结构的第一步。

use Data::Dumper;
print Dumper($hash);

产生以下输出:

$VAR1 = {
          'gene_res' => {
                          'gene' => [
                                      {
                                        'gname' => {
                                                     'variant' => [
                                                                    {
                                                                      'an' => 2,
                                                                      'annotation' => ''
                                                                    }
                                                                  ]
                                                   }
                                      }
                                    ]
                        }
        };

我修改了您的printingMeta子例程,以访问annotationan字段。

sub printingMeta {
    my $hash = decode_json($_[0]);

    foreach my $gene ( @{ $hash->{gene_res}{gene}} ) {

        foreach my $variant ( @{ $gene->{gname}{variant}} ) {

            print $variant->{an}, "\t", $variant->{annotation}, "\n";
        }
    }
}

我不完全确定您要实现的目标,但上述代码可让您访问annotationan字段。

答案 2 :(得分:1)

如果在潜入过程中保持一个中间变量指向结构的每个级别,那么访问嵌套数据结构要容易得多

您还必须使用Data::Dumper(或者最好Data::Dump,这会产生较少的蔓延输出,但不是核心模块,因此可能需要安装)来检查数据结构你必须在每个级别处理。这样很明显 - 如果它以大括号{开头,那么它是一个哈希引用,或者如果它以方括号[开头,则它是一个数组引用

例如,如果我使用dd $genes来显示

的结果
my $genes = $href->{gene_res}{gene};

然后我得到了这个输出

[{ gname => { variant => [{ an => 2, annotation => "" }] } }]

立即显示它是一个数组引用

您命名哈希引用$arrayref没有用处!在这段代码中,我仔细使用了单数名词来表示哈希引用,复数用于数组引用

您还可以使用each同时从哈希中获取键/值对

use strict;
use warnings 'all';

use JSON;
use Data::Dump;

my $json = '{"gene_res":{"gene":[{"gname":{"variant":[{"annotation":"","an":2}]}}]}}';

my $href = decode_json($json);

my $genes = $href->{gene_res}{gene};

for my $gene (@$genes) {

    #dd 'gene', $gene;

    while ( my ($gname, $variant) = each %$gene ) {

        print "gname      = $gname\n";
        #dd 'variant', $variant;

        my $variants = $variant->{variant};

        for my $variant ( @$variants ) {

            #dd 'variant', $variant;

            print "annotation = $variant->{annotation}\n";
            print "an         = $variant->{an}\n";
        }
    }
}