具有如下所示的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引用答案 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
子例程,以访问annotation
和an
字段。
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";
}
}
}
我不完全确定您要实现的目标,但上述代码可让您访问annotation
和an
字段。
答案 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";
}
}
}