我正在尝试从以下 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 中提取状态和标题?
答案 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
。