直接访问perl中的嵌套JSON数据?

时间:2017-03-05 14:41:46

标签: arrays json perl hash

我不熟悉Perl的哈希/引用语法,这会让我的眼睛受到伤害 我有以下JSON:

{
  "Arg":"Custom_Light state alias protocol",
  "Results": [
  {
    "Name":"Custom_Light",
    "Internals": { },
    "Readings": {
      "protocol": { "Value":"V3", "Time":"2017-01-14 18:49:18" },
      "state": { "Value":"off", "Time":"2017-03-05 10:39:50" }
    },
    "Attributes": {      "alias": "Kitchen light" }
  }  ],
  "totalResultsReturned":1
}

如何直接阅读>协议值和阅读>状态值以及属性>别名?

我正在使用默认的JSON编码器/解码器,它非常出色。使用Dumper($json)我得到了所有的JSON,但我不知道如何直接访问它而不使用foreach和数组中的所有数组。

我尝试了以下内容:

my $json = from_json( $readout, { utf8  => 1 } );
print "No. Entries:", scalar(keys($json)); #works, returns 3
my @results = %$json{Results};
Dumper(@results[1]); #I get the Results array

从这里起,它已经很难看了。 %$在那里做什么?我以为我可以做print ${ $json->{'Results'}->[1] }{'Readings'};这样的事情,但这导致我无处可去。

给我智慧。如何直接访问协议值?如何直接访问状态值?最后,如何获取别名属性?

我不知道我在做什么,但我正在my $test = %{${%$json{Results}}[0]}{Name}; #I get "Custom_Light", nice的某个地方。这是随机投入的大量奇怪%$的方式吗?

2 个答案:

答案 0 :(得分:5)

你想要

$json->{Results}[0]{Readings}{protocol}{Value}
$json->{Results}[0]{Readings}{state}{Value}
$json->{Results}[0]{Attributes}{alias}

但是,由于Results项是一个数组,您可能希望迭代其所有元素,尽管在这种情况下只有一个元素

我发现将一级引用一次提取到临时变量中很有用。它看起来像这样

my $results = $json->{Results};

for my $result ( @$results ) {

    my $readings   = $result->{Readings};
    my $attributes = $result->{Attributes};

    printf "Protocol: %s\n", $readings->{protocol}{Value};
    printf "State:    %s\n", $readings->{state}{Value};
    printf "Alias:    %s\n", $attributes->{alias};
    print "\n";
}

答案 1 :(得分:1)

查看perlreftutperldscperlref,它将帮助您了解如何在Perl中访问深层嵌套结构。

  

打印"没有。条目:",标量(键($ json)); #works,返回3

实际上,这将不再有效。在标量上使用keys是Perl 5.14中添加的实验性功能,允许eachkeyspushpopshift,使用标量参数调用spliceunshiftvalues。该实验被认为是不成功的,并且在5.23中被删除。另见Experimental values on scalar is now forbidden。因此,在应用$json之前,您应该取消引用哈希引用keys

print "No. Entries:", scalar keys %$json;

perlref中所述,%$ref取消引用哈希引用$ref。接下来,让我们看看这一行:

  

我的@results =%$ json {结果};

这实际上首先会创建一个新的(匿名)哈希( Result => $json->{Result} ),然后将其分配给@results制作@result = ( 'Result', $json->{Result} )。这就是为什么您现在可以将$json->{Result}[0]称为$result[1]

但这是一个不起眼的编码,可能也不是那么好。所以要回到你的问题,获得你可以写的Value字段:

my $value = $json->{Results}[0]{Readings}{state}{Value};

获取alias字段:

my $alias = $json->{Results}[0]{Attributes}{alias};