在Perl中解码和使用JSON数据

don*_*uch 8 perl json

我很困惑访问我已解码的一些JSON数据的内容.这是一个例子

我不明白为什么这个解决方案有效,而我自己没有.我的问题在下面重述

my $json_raw = getJSON(); 
my $content  = decode_json($json_raw);
print Data::Dumper($content);
Run Code Online (Sandbox Code Playgroud)

此时我的JSON数据已经转化为此

$VAR1 = { 'items' => [ 1, 2, 3, 4 ] };
Run Code Online (Sandbox Code Playgroud)

我的猜测告诉我,一旦解码,该对象将是一个散列,其中一个元素具有键items,数组引用作为值.

$content{'items'}[0]
Run Code Online (Sandbox Code Playgroud)

where $content{'items'}将获取数组引用,外部$...[0]将访问数组中的第一个元素并将其解释为标量.但这不起作用.我收到一条错误消息use of uninitialized value [...]

但是,以下工作正常:

$content->{items}[0]
Run Code Online (Sandbox Code Playgroud)

其中$content->{items}产生数组引用并[0]访问该数组的第一个元素.

问题

  • 为什么不$content{'items'}返回数组引用?我甚至试过@{content{'items'}},想一想,一旦我得到了值content{'items'},它就需要被解释为一个数组.但是,我仍然收到未初始化的数组引用.

  • 如何在不使用箭头运算符的情况下访问数组引用?

caj*_*ine 10

初学者对初学者的回答:)当然不是应该如此专业,但也许可以帮助你.

use strict;    #use this all times
use warnings;  #this too - helps a lot!
use JSON;

my $json_str = '    { "items" : [ 1, 2, 3, 4 ] }    ';
my $content = decode_json($json_str);
Run Code Online (Sandbox Code Playgroud)

你写了:

我的猜测告诉我,一旦解码,该对象将是一个散列,其中一个元素具有关键项和数组引用作为值.

是的,它是一个哈希值,但decode_json返回一个引用,在本例中是对哈希的引用.(来自文档)

期望UTF-8(二进制)字符串并尝试将其解析为UTF-8编码的JSON文本,并返回结果引用.

在线

my $content = decode_json($json_str);
Run Code Online (Sandbox Code Playgroud)

您分配给SCALAR变量(不是哈希).

因为你知道:它是一个参考,你可以做下一个:

printf "reftype:%s\n", ref($content);
#print: reftype:HASH       ^   
           #therefore the  +------- is a SCALAR value containing a reference to hash
Run Code Online (Sandbox Code Playgroud)

它是一个hashref - 你可以转储所有密钥

print "key: $_\n" for keys %{$content}; #or in short %$content
#prints: key: items
Run Code Online (Sandbox Code Playgroud)

你也可以将"items"(arrayref)的值赋给标量变量

my $aref = $content->{items};   #$hashref->{key}
#or
#my $aref = ${$content}{items}; #$hash{key}
Run Code Online (Sandbox Code Playgroud)

不是

#my $aref = $content{items};    #throws error if "use strict;"
#Global symbol "%content" requires explicit package name at script.pl line 20.
Run Code Online (Sandbox Code Playgroud)

$content{item}请求从哈希值%content,你永远不定义/分配这样的变量.这$content是一个标量变量而不是哈希变量%content.

{
    #in perl 5.20 you can also
    use 5.020;
    use experimental 'postderef';
    print "key-postderef: $_\n" for keys $content->%*;
}
Run Code Online (Sandbox Code Playgroud)

现在再深入 - 到arrayref - 再次打印出引用类型

printf "reftype:%s\n", ref($aref);
#reftype:ARRAY
Run Code Online (Sandbox Code Playgroud)

打印数组的所有元素

print "arr-item: $_\n" for @{$aref};
Run Code Online (Sandbox Code Playgroud)

但同样不是

#print "$_\n" for @aref;
#dies: Global symbol "@aref" requires explicit package name at script.pl line 37.

{
    #in perl 5.20 you can also
    use 5.020;
    use experimental 'postderef';
    print "aref-postderef: $_\n" for $aref->@*;
}
Run Code Online (Sandbox Code Playgroud)

这是一个简单的规则:

my @arr;               #array variable
my $arr_ref = \@arr;   #scalar - containing a reference to @arr

@{$arr_ref} is the same as @arr 
 ^^^^^^^^^^ - array reference in curly brackets
Run Code Online (Sandbox Code Playgroud)

如果你有$arrayref- 使用@{$array_ref}你想要的任何地方使用数组.

my %hash;              #hash variable
my $hash_ref = \%hash; #scalar - containing a reference to %hash

%{$hash_ref} is the same as %hash
 ^^^^^^^^^^^ - hash reference in curly brackets
Run Code Online (Sandbox Code Playgroud)

如果你有$hash_ref- 使用%{$hash_ref}你想要的任何地方使用哈希.

对于整个结构,以下

say $content->{items}->[0];
say $content->{items}[0];
say ${$content}{items}->[0];
say ${$content}{items}[0];
say ${$content->{items}}[0];
say ${${$content}{items}}[0];
Run Code Online (Sandbox Code Playgroud)

打印相同的值1.


Eri*_*all 5

$content是哈希引用,因此您始终需要使用箭头来访问其内容。$content{items}会指代%content您没有的哈希。那就是从那里得到“未初始化值的使用”错误的地方。

  • TMTOWTDI再次来袭! (3认同)
  • 取消引用时使用调用箭头的另一种方法是按照[perlref](http://perldoc.perl.org/perlref.html#Using-References)docs使用符号$$ content {items}`。 (2认同)