从复杂的 JSON 结构中提取数据

时间:2021-07-09 08:27:19

标签: json perl

我正在尝试从以下 json 结构中提取一些数据:

{
    "numFailedTestSuites": 0,
    "numFailedTests": 0,
    "numPassedTestSuites": 7,
    "numPassedTests": 29,
    "numPendingTestSuites": 0,
    "numPendingTests": 0,
    "testResults": [
        {
            "assertionResults": [
                {
                    "ancestorTitles": [
                        "propertyReader"
                    ],
                    "failureMessages": [],
                    "fullName": "propertyReader Test method: readPropertyFile",
                    "location": null,
                    "status": "passed",
                    "title": "Test method: readPropertyFile"
                }
            ]
        },
        {
            "assertionResults": [
                {
                    "ancestorTitles": [
                        "Transform Angle"
                    ],
                    "failureMessages": [],
                    "fullName": "Transform Angle Test Method: rotationMatrix",
                    "location": null,
                    "status": "passed",
                    "title": "Test Method: rotationMatrix"
              }
            ]
        }
    ]
}

特别是,我需要访问状态和标题。这是我写的:

my $dir = getcwd();
my $jsonFilePath="testResult.json";
my $finalPath=$dir."/".$jsonFilePath;

print "json file path is ",$finalPath;
my $json = $finalPath;

my $data = do {
    open my $fh, '<', $json;
    local $/;
    decode_json(<$fh>);
};

my $results = $data->{testResults};
for my $result ( @$results ) {

    my $readings   = $result->{assertionResults};
    printf "status: %s\n", $readings->{status};
    printf "title:    %s\n", $readings->{title};
    print "\n";
}

我收到以下错误:

<块引用>

不推荐使用伪哈希
第 27 行的散列元素中的参数“passed”不是数字(printf "status: %s\n", $readings->{status};)
在第 27 行将数组强制转换为散列时索引错误。

如何修复这些错误并从上面的 JSON 中提取状态和标题?

2 个答案:

答案 0 :(得分:2)

首先,您的 JSON 无效:您在最后一个 ] 之前缺少一个结束 }(这将关闭与键 testResults 关联的数组)。通过添加缺少的 ] 来修复 JSON 的语法将修复以下错误消息:

<块引用>

或 ] 预期解析数组时,字符偏移量 1128(在“}\n”之前)在 ...

其次,assertionResults 包含一个 JSON 数组(然后在 Perl 中转换为 arrayref)而不是一个对象(它会被转换为 hashref)。因此,您应该在执行 $readings->{status}:

时收到此错误 <块引用>

在 json.pl 行不是 HASH 引用...

要修复它,请将 $result->{assertionResults} 视为 arrayref 而不是 hashref。看来你想做的是:

my $readings = $result->{assertionResults}[0];

话虽如此,根据您的 JSON 实际可以包含的内容,您可能想要这样做:

for my $readings (@{$result->{assertionResults}}) {
    printf "status: %s\n", $readings->{status};
    printf "title:  %s\n", $readings->{title};
    print "\n";
}

或者,也许您没有按照自己的意愿构建 JSON,而是

    "assertionResults": [
        {
            "ancestorTitles": [
                "propertyReader"
            ],
            "failureMessages": [],
            "fullName": "propertyReader Test method: readPropertyFile",
            "location": null,
            "status": "passed",
            "title": "Test method: readPropertyFile"
        }
    ]

您可能想要删除方括号 [] 并有

    "assertionResults":
        {
            "ancestorTitles": [
                "propertyReader"
            ],
            "failureMessages": [],
            "fullName": "propertyReader Test method: readPropertyFile",
            "location": null,
            "status": "passed",
            "title": "Test method: readPropertyFile"
        }

答案 1 :(得分:1)

请调查以下代码片段是否符合您的问题。

use strict;
use warnings;
use feature 'say';

use JSON;

my $json = do { local $/; <DATA> };
my $data = from_json($json);

say "$_->{assertionResults}[0]{title}   $_->{assertionResults}[0]{status}"
    for  @{$data->{testResults}};


__DATA__
{
    "numFailedTestSuites": 0,
    "numFailedTests": 0,
    "numPassedTestSuites": 7,
    "numPassedTests": 29,
    "numPendingTestSuites": 0,
    "numPendingTests": 0,
    "testResults": [
        {
            "assertionResults": [
                {
                    "ancestorTitles": [
                        "propertyReader"
                    ],
                    "failureMessages": [],
                    "fullName": "propertyReader Test method: readPropertyFile",
                    "location": null,
                    "status": "passed",
                    "title": "Test method: readPropertyFile"
                }
            ]
        },
        {
            "assertionResults": [
                {
                    "ancestorTitles": [
                        "Transform Angle"
                    ],
                    "failureMessages": [],
                    "fullName": "Transform Angle Test Method: rotationMatrix",
                    "location": null,
                    "status": "passed",
                    "title": "Test Method: rotationMatrix"
              }
            ]
        }
    ]
}

输出

Test method: readPropertyFile   passed
Test Method: rotationMatrix     passed

注意:

my $json = do { local $/; <DATA> }; 替换 my $json = do { local $/; <> }; 以读取作为脚本参数提供的文件。例如./script.pl datafile.json

这种方法允许利用管道将输入数据泵入脚本。例如cut datafile.json | ./script.pl