【问题标题】:Extracting data from complex JSON structure从复杂的JSON结构中提取数据
【发布时间】:2021-09-19 15:01:16
【问题描述】:

我正在尝试从以下是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 行哈希元素中的数字(printf "status: %s\n", $readings->{status};)
在第 27 行将数组强制转换为哈希时出现错误索引。

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

【问题讨论】:

  • 你遇到了什么错误?
  • 我没有收到与您相同的错误消息。这可能是因为我们使用了不同的 Perl 版本。或者可能是因为您没有发布您正在使用的实际代码或数据。如果我的回答不能解决您的问题,请确保当您运行问题中的确切代码/数据时,您会收到问题中显示的错误消息。
  • 执行jest test后生成json。原始 json 有超过 24000 行代码。这是实际数据的快照。您的解决方案对我有用,通过更改为我的 $readings (@{$result->{assertionResults}}) 感谢您的帮助!
  • 这种更改变量名称的做法有点过分,而且会使您的代码更难阅读。您的代码仅适用于 my $json = "testResult.json"。此外,getcwd 是完全没有必要的,因为 Perl 会假定所有文件路径都是相对于程序文件的位置。
  • 请注意,Perl 在双引号字符串中扩展变量。这意味着你可以写像my $finalPath="$dir/$jsonFilePath";print "json file path is $finalPath"; 这样的东西。您可能还会发现say() 函数比print() 更有用。

标签: json perl


【解决方案1】:

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

或 ] 解析数组时应在字符偏移 1128 处(“}\n”之前)...

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

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

要修复它,请将$result-&gt;{assertionResults} 视为数组引用而不是哈希引用。看来你想做的是:

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"
        }

【讨论】:

    【解决方案2】:

    请调查以下代码 sn-p 是否符合您的问题。

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多