Arrays 访问解码的JSON数据结构

Arrays 访问解码的JSON数据结构,arrays,json,perl,Arrays,Json,Perl,我试图使用Perl从这个JSON中提取一个特定的条目 { "sentences": [ { "index": 0, "tokens": [ { "index": 1, "word": "盧旺達", "origina

我试图使用Perl从这个JSON中提取一个特定的条目

{
    "sentences": [
        {
            "index": 0,
            "tokens": [
                {
                    "index":                1,
                    "word":                 "盧旺達",
                    "originalText":         "盧旺達",
                    "lemma":                "盧旺達",
                    "characterOffsetBegin": 0,
                    "characterOffsetEnd":   3,
                    "pos":                  "NN",
                    "ner":                  "PERSON"
                },
                {
                    "index":                2,
                    "word":                 "援助",
                    "originalText":         "援助",
                    "lemma":                "援助",
                    "characterOffsetBegin": 3,
                    "characterOffsetEnd":   5,
                    "pos":                  "NN",
                    "ner":                  "O"
                }
            ]
        }
    ]
}
我想访问
tokens
,然后访问
ner
,我一直在尝试使用此代码,但它没有返回任何内容

$json = decode_json $json_string;

my $tokens = $json->{"sentences"}->{"tokens"};

print Dumper(\$tokens);

JSON对象用
{}
表示,数组用
[]
表示。您在尝试中丢失了两个级别的阵列:

{                                    # $json
    "sentences": [                   # $json->{sentences}
        {                            # $json->{sentences}->[0]
            "tokens": [              # $json->{sentences}->[0]->{tokens}
                {                    # $json->{sentences}->[0]->{tokens}->[0]
                    "ner": "PERSON"  # $json->{sentences}->[0]->{tokens}->[0]->{ner}
因此,与此相反:

$json->{sequences}->{tokens}

你想要这个:

$json->{sequences}->[0]->{tokens}->[0]->{ner}

如果您想要
ner
键的所有值,而不仅仅是
语句
标记
的特定下标处的值,则需要使用迭代:

my $obj = decode_json($json);

for my $sentence (@{$obj->{sentences}}) {
    for my $token (@{$sentence->{tokens}}) {
        print "$token->{ner}\n";
    }
}

看。当然,如果必须与较旧的
perl
s兼容,您可以使用
{$x->{sequences}}
{$sequence->{tokens}}

sequences
是一个数组。我不知道Perl,但它看起来就像是一个普通对象一样访问它。那么,或许可以先尝试获取第一个索引?猜一猜。
句子
数组可能有多个元素。你想从所有的
语句中的
标记中得到
ner
吗?如果你告诉我们你肯定从这段代码中得到的错误消息,那会有很大帮助。我认为语法应该是
$json->{句子}[0]{tokens}
,这是一个有用的教训。我不知道这是否是故意的,但我同意Brian的
无警告qw(实验性::postderef)
在生产代码中是不合适的。如果你打算使用实验性的特性,那么你很想得到一个警告,提醒你可能的错误来源。“干净”的构建并不是一个很好的目标。
使用v5.24;#为什么不?!
“因为您专门使用它来启用
postderef
(和
say
)功能,这一点并不明显。作为记录,上面的“为什么不?!”是为了开玩笑地诱使您尝试最近的
perl
的好功能。这并不是对
5.24
之前的博客文章的评论。这是一个适合OP级别的有用且简洁的介绍(对Perl初学者来说比关于该特性的官方文档更有帮助)。我并不认为这是一个批评,我的“我同意”是不合适的。事后看来,我会写“……但我赞扬Brian没有使用相应的
无警告qw/experimental::postderef/
”。正是那些使用了
无警告
的人,因为v5.28已经停止了
实验::smartmatch
而感到不安。同时,我也会注意编写功能完整的代码,甚至包括一行shebang代码,这是您不希望在生产代码中看到的。不管你喜欢与否,你是一个权威,人们都会喜欢你。我必须补充一点,尝试任何
perl
的任何特性都是值得称赞的。几分钟的积极实验将很快纠正对Perl运算符的许多误解,例如
my@parts=split/;/@今天才出现的数据,知识将被吸收而不是应用和丢弃。
#!/usr/bin/env perl

use v5.24; # why not?!
use utf8;
use strict;
use warnings;

use open qw(:std utf8);

use JSON::MaybeXS qw( decode_json );

my $json = "...";

my $x = decode_json $json;

for my $sentence ($x->{sentences}->@*) {
    for my $token ($sentence->{tokens}->@*) {
        say $token->{ner};
    }
}