我将如何在Perl中读取此数据结构?具有包含包含列表的列表的键的字典/哈希。Python :: Inline给我错误

CRE*_*REW 2 python perl hash inline list

在这个简单的问题上,我已经苦苦挣扎了大约3个星期。我不明白为什么,我会给任何解决的办法。

我正在尝试从下面的数据结构中读取值。文档说这是一本字典,其中的键包含该类型结果的列表。

示例:我使用eval函数获得主查询答复。我查找键“ song_hits”以获取该结构。然后,我查找键“ track”并进行解析。问题出在“跟踪”部分。

当我按照Perl文档告诉我的那样执行操作时,我通过包“ Inline :: Python :: Object :: Data”得到了无法找到对象方法“ FIRSTKEY”的信息。

所以我想知道是否有一种方法可以使用eval函数绕过ObjectData的哈希键限制来读取该值,或者是在我知道确切的键的情况下另一种读取该值的方法,或者我是否这样做完全错误。

{
'album_hits': [
{
    'album':
    {
        'albumArtRef': 'http://lh5.ggpht.com/DVIg4GiD6msHfgPs_Vu_2eRxCyAoz0fF...',
        'albumArtist': 'J.Cole',
        'albumId': 'Bfp2tuhynyqppnp6zennhmf6w3y',
        'artist': 'J.Cole',
        'artistId': ['Ajgnxme45wcqqv44vykrleifpji'],
        'description_attribution':
        {
            'kind': 'sj#attribution',
            'license_title': 'Creative Commons Attribution CC-BY',
            'license_url': 'http://creativecommons.org/licenses/by/4.0/legalcode',
            'source_title': 'Freebase',
            'source_url': ''
        },
        'explicitType': '1',
        'kind': 'sj#album',
        'name': 'Work Out',
        'year': 2011
    },
    'type': '3'
}],
'artist_hits': [
{
    'artist':
    {
        'artistArtRef': 'http://lh3.googleusercontent.com/MJe-cDw9uQ-pUagoLlm...',
        'artistArtRefs': [
        {
            'aspectRatio': '2',
            'autogen': False,
            'kind': 'sj#imageRef',
            'url': 'http://lh3.googleusercontent.com/MJe-cDw9uQ-pUagoLlmKX3x_K...'
        }],
        'artistId': 'Ajgnxme45wcqqv44vykrleifpji',
        'artist_bio_attribution':
        {
            'kind': 'sj#attribution',
            'source_title': 'David Jeffries, Rovi'
        },
        'kind': 'sj#artist',
        'name': 'J. Cole'
    },
    'type': '2'
}],
'playlist_hits': [
{
    'playlist':
    {
        'albumArtRef': [
        {
            'url': 'http://lh3.googleusercontent.com/KJsAhrg8Jk_5A4xYLA68LFC...'
        }],
        'description': 'Workout Plan ',
        'kind': 'sj#playlist',
        'name': 'Workout',
        'ownerName': 'Ida Sarver',
        'shareToken': 'AMaBXyktyF6Yy_G-8wQy8Rru0tkueIbIFblt2h0BpkvTzHDz-fFj6P...',
        'type': 'SHARED'
    },
    'type': '4'
}],
'situation_hits': [
{
    'situation':
    {
        'description': 'Level up and enter beast mode with some loud, aggressive music.',
        'id': 'Nrklpcyfewwrmodvtds5qlfp5ve',
        'imageUrl': 'http://lh3.googleusercontent.com/Cd8WRMaG_pDwjTC_dSPIIuf...',
        'title': 'Entering Beast Mode',
        'wideImageUrl': 'http://lh3.googleusercontent.com/8A9S-nTb5pfJLcpS8P...'
    },
    'type': '7'
}],
'song_hits': [
{
    'track':
    {
        'album': 'Work Out',
        'albumArtRef': [
        {
            'aspectRatio': '1',
            'autogen': False,
            'kind': 'sj#imageRef',
            'url': 'http://lh5.ggpht.com/DVIg4GiD6msHfgPs_Vu_2eRxCyAoz0fFdxj5w...'
        }],
        'albumArtist': 'J.Cole',
        'albumAvailableForPurchase': True,
        'albumId': 'Bfp2tuhynyqppnp6zennhmf6w3y',
        'artist': 'J Cole',
        'artistId': ['Ajgnxme45wcqqv44vykrleifpji', 'Ampniqsqcwxk7btbgh5ycujij5i'],
        'composer': '',
        'discNumber': 1,
        'durationMillis': '234000',
        'estimatedSize': '9368582',
        'explicitType': '1',
        'genre': 'Pop',
        'kind': 'sj#track',
        'nid': 'Tq3nsmzeumhilpegkimjcnbr6aq',
        'primaryVideo':
        {
            'id': '6PN78PS_QsM',
            'kind': 'sj#video',
            'thumbnails': [
            {
                'height': 180,
                'url': 'https://i.ytimg.com/vi/6PN78PS_QsM/mqdefault.jpg',
                'width': 320
            }]
        },
        'storeId': 'Tq3nsmzeumhilpegkimjcnbr6aq',
        'title': 'Work Out',
        'trackAvailableForPurchase': True,
        'trackAvailableForSubscription': True,
        'trackNumber': 1,
        'trackType': '7',
        'year': 2011
    },
    'type': '1'
}],
'station_hits': [
{
    'station':
    {
        'compositeArtRefs': [
        {
            'aspectRatio': '1',
            'kind': 'sj#imageRef',
            'url': 'http://lh3.googleusercontent.com/3aD9mFppy6PwjADnjwv_w...'
        }],
        'contentTypes': ['1'],
        'description': 'These riff-tastic metal tracks are perfect for getting the blood pumping.',
        'imageUrls': [
        {
            'aspectRatio': '1',
            'autogen': False,
            'kind': 'sj#imageRef',
            'url': 'http://lh5.ggpht.com/YNGkFdrtk43e8H941fuAHjflrNZ1CJUeqdoys...'
        }],
        'kind': 'sj#radioStation',
        'name': 'Heavy Metal Workout',
        'seed':
        {
            'curatedStationId': 'Lcwg73w3bd64hsrgarnorif52r',
            'kind': 'sj#radioSeed',
            'seedType': '9'
        },
        'skipEventHistory': [],
        'stationSeeds': [
        {
            'curatedStationId': 'Lcwg73w3bd64hsrgarnorif52r',
            'kind': 'sj#radioSeed',
            'seedType': '9'
        }]
    },
    'type': '6'
}],
'video_hits': [
{
    'score': 629.6226806640625,
    'type': '8',
    'youtube_video':
    {
        'id': '6PN78PS_QsM',
        'kind': 'sj#video',
        'thumbnails': [
        {
            'height': 180,
            'url': 'https://i.ytimg.com/vi/6PN78PS_QsM/mqdefault.jpg',
            'width': 320
        }],
        'title': 'J. Cole - Work Out'
    }
}]
Run Code Online (Sandbox Code Playgroud)

}

经过三周的不同尝试,已清理但已损坏的代码:(我曾尝试foreach,一会儿,但它读得最远的可能是整个unicode数组,错误或一个空字符串)

sub search {
    my $query = shift;

    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;
    }
    #gives not an ARRAY refernce error
    for my $hit (@{$googleResult->{song_hits}}) {
        push @{$result->{tracks}}, to_slim_track($hit->{track});
    }
    #works, but gives an error on the next line, 'newlist' object has no attribute 'album' 
    for my $hit ({$googleResult->{album_hits}}) {
        push @{$result->{albums}}, album_to_slim_album($hit->{album});
    }
    #Perl and others recommended way, but gives  Can't locate object method "FIRSTKEY" via package "Inline::Python::Object::Data"
    for my $hit (%{$googleResult->{artist_hits}}) {
        push @{$result->{artists}}, artist_to_slim_artist($hit->{artist});
    }

    # Add to the cache
    $cache->set($uri, $result, $CACHE_TIME);

    return $result;
}
Run Code Online (Sandbox Code Playgroud)

我尝试阅读,但遇到了很多错误,包括:

  • “密钥”不存在
  • 使用严格的引用时,不能将字符串(“ track”)用作HASH引用
  • 引用上键的自变量类型必须为无哈希值hashref或arrayref

我的完整测试文件:http : //pastebin.com/DMnDc56i GoogleApi PM(Python GAPI挂钩):https : //raw.githubusercontent.com/hechtus/squeezebox-googlemusic/master/GoogleMusic/GoogleAPI.pm

编辑:信息,有几个人想要修复未维护的旧代码,所以我提供了帮助,并且使这部分工作正常了。

旧代码Git:https : //github.com/hechtus/squeezebox-googlemusic

我使用的Google Api Python:https//github.com/simon-weber/gmusicapi

zdi*_*dim 5

我认为所示的数据结构在中$googleResult。这几乎是“几乎” JSON,您可以在简单清除后使用模块来进行处理。我将使用JSON :: XS。获取后,下面的代码将起飞$googleResult。(在测试中我实际复制在问题中所示到文件数据和读它)。我第一替换'通过"和小写TrueFalse,以获得其中该模块可以解码有效的JSON格式。

# Other code from the question ...
use JSON::XS;

# For tests I loaded shown data into $googleResult (did not run this eval)
eval {
    $googleResult = $googleapi->search($query, $prefs->get('max_search_items'));
};
if ($@) {
    $log->error("Not able to search All Access for \"$query\": $@");
    return;
}

# The structure shown in the question needs a cleanup
# But this may be a road to madness, if there is more
$googleResult =~ s/'/"/g;        # ' turn off wrong editor coloring
$googleResult =~ s/False/false/g;
$googleResult =~ s/True/true/g;

my $coder = JSON::XS->new;    
# There are many options for how to set it up. Example:
# JSON::XS->new->ascii->pretty->allow_nonref;    

my $data = $coder->decode($googleResult);  
# Now this is a normal Perl data structure that we can work with. 
# Look at what's under 'album_hits' for example
my $ralbhits = $data->{'album_hits'};  
print Dumper($ralbhits);
# We get: VAR1 = [ { 'album' => { albumID => ... } } ]
# Array reference, with nested hash references as the sole element

# Extract the 'artist'
my $artist = $ralbhits->[0]->{'album'}->{'artist'};
print "$artist\n";
Run Code Online (Sandbox Code Playgroud)

打印J. Cole(在我在这里省略的转储之后)。为了方便起见,您可以先提取结构的一部分,然后再更简单地对其进行查询。例如

# Get the hashref for album
my $ralbum = $ralbhits->[0]->{'album'};
my $artist = $ralbum->{'artist'};
Run Code Online (Sandbox Code Playgroud)

现在,将数据打包后,您可以根据artist_to_slim_artist()需要和执行的操作检索需要的内容。这是正常的数据结构。

用于JSON解析的模块返回Perl数据结构,请参见JSON :: XS中的映射。通常,除非非常简单的情况,否则它们将被嵌套。有关如何与他们合作的信息,请参阅perldsc,这是一本有关复杂数据结构的食谱。


JSON本示例中给出的对象虽然无效,但几乎不需要校正。但是,它可能变得更加复杂。例如,100kB在注释中链接了一个更大的文档(〜),出现了这些问题。

  • 名称-值对用'代替," 值本身包含'(如isn't和其他收缩),这使对的匹配变得复杂'

  • u'名称和值开头的无效序列(u需要删除)。可以将它们与上面的内容一起滚动。也有u"

  • 文本可能包含各种转义符,例如某些重音符号编码,这些编码不是有效的JSON。(该文档中的一个。)可以找到并解决(例如,转义)。

花了几分钟的时间提出了一些正则表达式,用于纠正链接上的文档,该文档的大小接近100kB,因此可以使用上述代码清晰地进行解析。但是问题在于,很难在下一个文档中分辨出其他问题。不过,由于这可能令人感兴趣,因此这里是正则表达式。

"名称和值不是放在一对中,而是在它们之间',并且前者也有一个额外的字符,u'。使得结束变得容易的是,'任何一个都必须在结束之后,, : ] }并且我使用肯定的前瞻性来断言。最后,有一些u"开头的引号u已被删除。

$googleResult =~ s/False/false/g;
$googleResult =~ s/True/true/g;
$googleResult =~ s/u"/"/g;
# There are also escaped characters in text, escape that backslash
$googleResult =~ s|(\\)|$1$1|g;
# Correct delimiters from u'...' to "...", see text below   
$googleResult =~ s/u'(.*?)' (?= []:},] )/"$1"/gx;
# We are good now, decode it
my $data = $coder->decode($googleResult); 
my $alb = $data->[0]{track}{album};
print "$alb\n";
Run Code Online (Sandbox Code Playgroud)

打印These Things Happen(正确)。在上面,我们捕获了之间u'以及第一个'之后的第一个,后面是两个 ]:,}(使用字符类[...])。然后u''由代替""。完成这项decode($googleResult);工作后,我们将获得要查询的Perl数据结构。

有许多模块允许“放松”方法,并且将接受许多此类不合规定之处。但是,通过使用它们,我们同意使用无效的JSON,这意味着它是一种简单明了的数据格式,我不建议您这样做。请注意,该格式的几乎完整规范非常适合上述链接中一个清晰且慷慨地说明的页面。另请参阅JSON Example,以获取一些示例。

我认为最好的选择是尝试清理它。像上面的代码一样运行解码器,然后查看错误消息。它将准确地找出问题所在。然后添加一个正则表达式来更正这种特殊的格式冲突。然后再去。如果您使用的各种文档或多或少都带有相同的问题集(例如上述问题),则可能会很好。否则,如果不断出现新的违规情况,那就太麻烦了,在这种情况下,您可能需要使用其他方法。

最后,我不知道您是如何从最初的Python对象问题中得出这种格式的。格式是否可能在翻译中被破坏了?我不知道那是怎么回事。难道实际上不是JSON吗?但是,它离它太近了。

是否可以要求提供有效的JSON?