【问题标题】:Access Data Dumper nested Perl Hash访问数据转储程序嵌套的 Perl 哈希
【发布时间】:2015-04-01 11:09:44
【问题描述】:

我有一个 Perl 哈希引用 $artifact,我正在使用 Data::Dumper 打印它。

print Dumper ($artifact); 的输出返回以下内容。

$VAR1 = bless( {
             '_content' => '{
  "results" : [ {
"uri" : "http://localhost:port/myfile.tar"
   } ]
}',);

但是,我在尝试专门访问 URI 的值时遇到了麻烦,即我想检查 uri 是否有值。

谢谢!

编辑:只是一些上下文。我正在使用 Artifactory::Client perl 模块中的“artifact_search”方法

【问题讨论】:

  • 这是 Dumper 输出的直接复制/粘贴吗?这不会解析(您在bless 上缺少关闭})并且如果没有将它祝福到特定类(可能包括访问内容的方法),您不太可能拥有祝福引用。
  • @MichaelCarman 道歉 - 我刚刚提取了我需要使用的数据转储器输出的一部分。 print Dumper ($artifact) 返回更多但不相关。
  • 来自synopsis section of the Artifactory::Client documentation:“此模块中提供的每个公共方法都返回一个HTTP::Response 对象。”您应该使用HTTP::Response API,而不是自己在内部进行探索。

标签: json perl hash hashref data-dumper


【解决方案1】:

要从哈希引用中提取信息,首先需要取消引用。您可以:

print ${$artifact}{uri},"\n"; 

在这种特定情况下,您可以省略大括号并执行以下操作:

print $$artifact{uri},"\n"; 

但请注意,这可能是模棱两可的,因此符号样式并不总是适用于取消引用。

或者更新的,可能更清晰的符号(例如面向对象)

print $artifact->{uri},"\n";

但是,这里有一个很大的警钟 - bless - 这意味着你可能正在操纵一个对象。在物体内部戳是非常脏的。你永远不应该这样做。 通常该对象将包含一个访问器方法来为您提供所需的信息。按照惯例,_ 前缀表示private,例如'不要惹这个'。 (反正你不应该这样做)

如 cmets 中所述 - 这是嵌入在对象中的 JSON 文本字符串。因此,如果您真的打算这样做 - 您可以解析 JSON,将其转换为 perl 数据结构,然后使用它。

但更有可能 - 您正在操作的对象有一些内置的访问器方法,您应该使用它们。

所以给出你上面的例子:

#!/usr/bin/perl

use strict;
use warnings;
use Data::Dumper;
use JSON;

my $hashref = {
    _content => '{
      "results" : [ {
"uri" : "http://localhost:port/myfile.tar"
   } ]
}'
};

print Dumper \$hashref;

my $json    = JSON->new();
my $json_ob = $json->decode( $hashref->{_content} );
print Dumper \$json_ob;
print $json_ob ->{results}->[0]->{uri};

但是,如 cmets 中所述,您正在使用: Artifactory::Client 非常明智地使用了LWP

此模块中提供的每个公共方法都返回一个 HTTP::Response 对象。

参考HTTP::Response 文档给出了这个示例:

if ($artifact->is_success) {
    print $artifact->decoded_content;
}
else {
    print STDERR $artifact->status_line, "\n";
}

【讨论】:

  • 唯一的键是_content。 URI 被编码到值中。
  • 再看一遍。 _content 之后的所有内容都是编码为 JSON/YAML 的字符串。
  • 啊,是的。好的。 JSON 在私有字段中嵌入对象。这让我觉得很痛苦。
【解决方案2】:

就 Perl 而言,您的 $artifact 变量是具有单个键/值对的哈希引用。 URI 嵌入在值中,看起来是 JSON。您需要提取值、解析它,然后获取 URI。

JSON 是 YAML 的有效子集,因此您可以使用 YAML 模块对其进行解析。

use YAML::XS;
my $content = $artifact->{_content};
my $yaml    = Load($content);
print $yaml->{results}[0]{uri}; # http://localhost:port/myfile.tar

也就是说,方法/属性名称上的前导下划线通常意味着它们是类的“私有”,不应在外部使用。窥视 API 背后(如果不知道数据来自哪里以及 $artifact 属于哪个类,我们就无法知道它)是脆弱的。

【讨论】:

  • Rails 的人认为他们也可以使用 YAML 解析器来处理 JSON :) 如果你想解析 JSON,为什么要让它更复杂呢?使用不具备所有额外功能(例如对象创建和销毁)的 JSON 解析器。
【解决方案3】:

这不是您从 Dumper 获得的确切输出,是吗?如果 Dumper 输出包括对 bless 的调用,那么它还应该包括引用已被祝福的类的名称。

天真的方法是这样的:

print $artifact->{_content}{results}[0]{uri};

但鉴于您似乎拥有一个对象(一个祝福的哈希引用),那么几乎可以肯定类上会有访问对象属性的方法。您应该使用这些而不是在对象的内部进行挖掘。

更新:是的,我错过了整个 _content 键是一个 JSON 字符串。很抱歉:-/

【讨论】:

  • 虽然我同意应该有一个类,但可以祝福一个参考而不指定一个。但是,您不能直接访问uri_content 之后的所有内容都是 JSON/YAML 字符串。
  • 确实 - 我刚刚被抓到了 - 尽管乍一看像 Data::Dumper 输出,这都是一个字符串,而不是数据结构。
  • @MichaelCarman:您当然可以在不指定类的情况下调用bless()。但是你的祝福散列仍然会附加一个类——它将是当前包。试试perl -MData::Dumper -E' $o=bless({}), say Dumper $o'
猜你喜欢
  • 2011-02-14
  • 2018-12-17
  • 1970-01-01
  • 1970-01-01
  • 2012-11-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-06
相关资源
最近更新 更多