【问题标题】:json parsing - Get values only under conditionsjson 解析 - 仅在条件下获取值
【发布时间】:2021-08-04 10:35:48
【问题描述】:

我正在尝试解析此 JSON 文件以获取一些特定值。 我想要实现的是获得“生成器”和“有效负载”值。棘手的是有些项目包含两个结果,有些生成器也有两个项目。在这种情况下,我只对带有元数据信息的有效载荷值感兴趣。

期望的输出:

agentinfo, 3p95ouql5QgiZ2M7MBBQH5
log-audit, dWdVpfCCm44ax4KCyTEmhL
config, 1gi1QRjxme267adKl7Kqzn

我设法使用jq '.audits[] | .generator, .results[].payload' manifest.json 获得了生成器和结果,但输出并不完全符合我的预期。还尝试了selectunique_by,但我没有得到我想要的。

{
    "type": "audit_manifest",
    "version": "1.0",
    "audits": [

        {
            "id": "",
            "generator": "agentinfo",
            "generatorVersion": "1.0.0.0",
            "results": [
                {
                    "payload": "3p95ouql5QgiZ2M7MBBQH5",
                    "type": "application/json"
                }
            ]
        },
        {
            "id": "",
            "generator": "log-audit",
            "generatorVersion": "1.0.0.0",
            "results": [
                {
                    "payload": "m3q1IVhgNk59VySdnvEXgk",
                    "type": "application/json"
                },
                {
                    "payload": "dWdVpfCCm44ax4KCyTEmhL",
                    "type": "application/octet-stream",
                    "metadata": [
                        {
                            "name": "name",
                            "value": "agent.log"
                        }
                    ]
                }
            ]
        },
        {
            "id": "",
            "generator": "log-audit",
            "generatorVersion": "1.0.0.0",
            "results": [
                {
                    "payload": "80iINCJwFFjcLp3BUf9Tec",
                    "type": "application/json"
                }
            ]
        },
        {
            "id": "",
            "generator": "config",
            "generatorVersion": "1.0.0.0",
            "results": [
                {
                    "payload": "hRUiHto5JpcjnbD3tJQMx1",
                    "type": "application/json"
                },
                {
                    "payload": "1gi1QRjxme267adKl7Kqzn",
                    "type": "application/octet-stream",
                    "metadata": [
                        {
                            "name": "name",
                            "value": "config.json"
                        }
                    ]
                }
            ]
        },
        {
            "id": "",
            "generator": "config",
            "generatorVersion": "1.0.0.0",
            "results": [
                {
                    "payload": "SGf26By1b174bCLD0YYx01",
                    "type": "application/json"
                }
            ]
        }
    ]
}

一如既往,感谢您的建议!

【问题讨论】:

    标签: json jq


    【解决方案1】:
    jq -r '
      reduce(.audits[] | {generator} * .results[]) as $item ({}; 
        (.[$item.generator]?) as $left
        | . * {($item.generator):
                 (if ($left | has("metadata"))
                  then $left else $item end) })
      | .[]
      | "\(.generator),\(.payload)"'
    

    输出:

    agentinfo,3p95ouql5QgiZ2M7MBBQH5
    log-audit,dWdVpfCCm44ax4KCyTEmhL
    config,1gi1QRjxme267adKl7Kqzn
    

    稍微分解一下:

    • .audits[] | {generator} * .results[] 生成一个“结果”对象的平面列表,这些对象知道哪个生成器生成了它们
    • 我们reduce 使用以下逻辑列出该列表。减少将从种子状态(一个空对象)开始,并评估表达式,其中. 设置为中间状态,$item 设置为展平列表的元素。表达式的输出成为新的中间状态。最后,状态返回到管道中的下一步。
      • (.[$item.generator]?) as $left:我们查找中间状态的生成器。如果还不存在,则此表达式将生成 null
      • . * {($item.generator): ...}:我们用$item.generator 的条目扩展了中间状态
      • if ($left | has("metadata")) then $left else $item end:我们选择具有元数据键的项目,否则选择传入的项目。如果这是我们第一次看到该键,$left 就是 null,不会有元数据键。
    • .[]:仅从结果对象中获取值
    • "\(.generator),\(.payload)":生成一个漂亮的字符串。

    【讨论】:

      【解决方案2】:

      这是使用group_by 的简单方法:

      jq -r '
        [ .audits[]
          | .generator as $generator
          | .results
          | (map(select(.payload)) | length) as $npayloads
          | (if $npayloads == 1 then (.[] | select(.payload).payload)
             else first(.[] | select(.metadata).payload)
             end)  as $payload
          | {$generator, $payload} ]
        | group_by(.generator)
        | map(.[0])[]
        | "\(.generator),\(.payload)"
      '
      

      这会产生所需的输出,但您可能希望考虑使用 @csv 以确保输出作为 CSV 有效。​​

      【讨论】:

        猜你喜欢
        • 2018-05-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-06-08
        • 2021-10-15
        • 1970-01-01
        • 2020-07-07
        相关资源
        最近更新 更多