尝试更新旧的 Perl 代码时不是 ARRAY 引用。哈希到数组问题?

Not an ARRAY reference when trying to trying to update old Perl code. Hash to Array issue?

我正在尝试将过时的 perl 插件更新为 Google 的新 API(他们更改了搜索调用)。我是 Perl 的新手,所以我不确定如何正确更新代码。我很确定我正在尝试读取一个散列,而它应该是一个数组?

已转储数据结构:

$VAR1 = {
          'station_hits' => bless( do{\(my $o = 1726698624)}, 'Inline::Python::Object' ),
          'album_hits' => bless( do{\(my $o = 1726698288)}, 'Inline::Python::Object' ),
          'artist_hits' => bless( do{\(my $o = 1726698336)}, 'Inline::Python::Object' ),
          'situation_hits' => bless( do{\(my $o = 1726698384)}, 'Inline::Python::Object' ),
          'song_hits' => bless( do{\(my $o = 1726698432)}, 'Inline::Python::Object' ),
          'playlist_hits' => bless( do{\(my $o = 1726698480)}, 'Inline::Python::Object' ),
          'video_hits' => bless( do{\(my $o = 1726698528)}, 'Inline::Python::Object' )
        };

代码块:

# Search All Access
sub search {
        my $query = shift;

        return unless $prefs->get('all_access_enabled');

        my $uri = 'googlemusic:search:' . $query;

        if (my $result = $cache->get($uri)) {
                return $result;
        }

        my $googleResult;
        my $result = {
                tracks => [],
                albums => [],
                artists => [],
        };

        eval {
                $googleResult = $googleapi->search($query, $prefs->get('max_search_items'));
        };

        if ($@) {
                $log->error("Not able to search All Access for \"$query\": $@");
                return;
        }
        #My Attempt
        for my $hit (%@{$googleResult->{song_hits}}) {
                push @{$result->{tracks}}, to_slim_track($hit->{track});
        }
        #How it was originally
        for my $hit (@{$googleResult->{album_hits}}) {
                push @{$result->{albums}}, album_to_slim_album($hit->{album});
        }

仅更改名称后出现此错误:

[LINE#]

不是 ARRAY 引用

已将 search_all_access 更改为 搜索

有问题的行:

for my $hit (@{$googleResult->{song_hits}}) {

我尝试研究并在前面添加了一个 %,但现在我在下一行收到错误。

'newlist' 对象在 [LINE#+1]

处没有属性 'track'
 push @{$result->{tracks}}, to_slim_track($hit->{track});

编辑: 在很好地解释引用散列应该如何工作后进行更改后,我得到了这个:

 [16-05-23 10:22:36.7283] Slim::Networking::IO::Select::__ANON__ (131) Error: Select task failed calling Slim::Web::HTTP::processHTTP: Can't locate object method "FIRSTKEY" via package "Inline::Python::Object::Data" at /usr/lib/arm-linux-gnueabihf/perl/5.20/Data/Dumper.pm line 224.
; fh=Slim::Web::HTTP::ClientConn=GLOB(0x1007a188)

我不确定他们的代码中是否存在错误,或者 Google 在最近这个错误之后以不同的结构返回 API 数据。

如果您使用 Data::Dumper 打印出这些数据结构,您很快就会看到它们是什么形式 in.Then 您将不必猜测。也不要将面向对象的调用风格误认为是哈希访问。 ,它们是相同的,因为这就是 Perl5 对象的制作方式。

use data::dumper;
print "variable is :" + Dumper(@variable)

这些对象似乎被抽象掉了。您可以阅读 Inline::Python documentation, but there's nothing about it. In the code for the Inline::Python::Object 但是,有一个提示。

往下两行,有这个(我的漏)。

use overload '%{}' => \&__data__, # [...]

如果它有 an overload 用于当它与散列解引用一起使用时,我们可以非常确定在这种情况下它会 return 一个散列引用。

现在我们需要做的就是修复您引入的语法错误。你做了 %@{},这是无效的语法。你需要 %{}.

而不是数组 deref @{}
for my $hit (%{ $googleResult->{song_hits} }) {
        push @{$result->{tracks}}, to_slim_track($hit->{track});
}

但是因为 Perl 中的散列本质上是列表,所以您现在将遍历键和值。这几乎不是一个好主意。相反,您应该 iterate over the keys,然后使用它。或者更可能的是,您对它们中的每一个只有一个键感兴趣。如果有 API 描述,我建议您检查一下。在这里可能会有帮助。

如果没有,Dumper像这样。

print Dumper \%{ $googleResult->{song_hits} };

首先取消引用它,确保调用重载。因为 Data::Dumper 不能将列表理解为数据结构,所以您向它传递了对 returned 散列的引用,因此您得到的是 $VAR1={} 而不是 $VAR1='foo'; $VAR2='bar' 等等。

我不明白“更新”的目的是什么,需要更改什么。但这里有一些评论。

第一:语法无效——不能有%@{...}。您可以 取消引用 对散列 %{$hashref} 或数组 @{$arrayref} (或标量 $$scalarref)的引用。


你的数据结构很有趣。首先,它是一个散列引用。 (或者更确切地说,一个 匿名散列 。)您可以完全取消引用它以创建一个散列,或者可以将特定键的值提取为

my $href = { 'k1' => 'val1', 'k2' => 'val2' };
my $value_of_k1_key = $href->{'k1'};            # will be == val1

接下来,你代码中的'value'正式成为一个对象。 bless 函数将对数据结构(通常是 hashref)的引用与 class 相关联,使其成为 class(returns)的对象。

所以你真的有

$href = { 'station_hits' => $object, ... }

查询(任何)键后,您将取回该对象。

$object = $googleResult->{song_hits}

根据“# How it is originally”(我认为可行)下显示的代码,对象的数据结构是对数组的引用,而不是散列,因为它取消引用一个数组。没关系。奇怪的是它直接取消引用它,寻找它的 data/attributes。在某些其他语言的术语中,它正在访问(大概)私有成员。在 Perl 中这是合法的并且会检索一个值,但它通常被认为和被禁止一样糟糕。