2013-07-08 51 views
2

首先,請在標題和正文中更正我所說的各種Perl語言結構!如何將變量作爲方法傳遞給Perl哈希引用?

我無法將變量傳遞給散列引用。具體來說,我使用JSON模塊來解碼一些JSON數據,然後訪問該數據的特定部分。

這裏是我的JSON數據的樣本:

[ 
{ 
    label:"Blah", 
    data:[ 
    [ 2112, 1 ] 
    ] 
} 
] 

現在,這裏是我的Perl代碼:

use JSON; 
use Data::Dumper; 
my $json = "*JSON data above*"; 
my $decoded_json = decode_json($json); 

# This works, prints out '2112': 
print(Dumper($decoded_json->[0]{'data'}[0][0])); 

# What I'd like to do: 
$datapath = "[0]{'data'}[0][0]"; 
print(Dumper($decoded_json->$datapath)); 

有沒有辦法做到這一點?謝謝!

+0

你可以使用'eval'來做這樣的事情,但那樣做真的很醜陋。你爲什麼要在字符串中編碼數據的「座標」?如果它到達一個字符串,你可以考慮使用一個正則表達式來將它拉出來,特別是如果你需要驗證的話。 –

+0

謝謝@JoeZ。數據以JSON格式的字符串(來自Web請求)到達。我不需要驗證它,我已經知道'座標'是什麼。不過,我試圖概括我的腳本,因爲我有不同的'$ datapath'個案。 PS>'eval'函數是如何被嘲笑的,這很有意思。到目前爲止,我變得'醜陋','皺眉'和'有問題'!具有諷刺意味的是,它似乎對我的情況非常好。 – KJH

回答

2

這通常是不可能的,但也有變通方法:

  1. 做一個與字符串eval

    my $val = do { 
        local [email protected]; 
        my $val = eval "\$decoded_json->$datapath"; 
        die [email protected] if [email protected]; 
        $val; 
    }; 
    

    當然,用這種方式使用eval是不滿意的。

  2. 定義一個走一個數據結構的功能:

    sub walk { 
        my $data = shift; 
        while (@_) { 
        my $index = shift; 
        if (ref $data eq 'HASH') { 
         $data = $data->{$index}; 
        } elsif (ref $data eq 'ARRAY') { 
         $data = $data->[$index]; 
        } else { 
         die qq(Wanted to use index "$index", but "$data" is neither hash nor array); 
        } 
        } 
        return $data; 
    } 
    
    my $val = walk($decoded_json, 0, 'data', 0, 0); 
    

    當然,這會失敗,重載對象。

3

儘管使用eval可以做到這一點,但這種方法存在問題。

我懷疑這是你的根本問題一個更好的答案:

use Data::Diver; 
my @datapath = (0, 'data', 0, 0); 
print(Dumper(Data::Diver::Dive($decoded_json, @datapath)));