【问题标题】:jq: Find a key in a struct in an array or use default value in jqjq:在数组中的结构中查找键或在 jq 中使用默认值
【发布时间】:2021-02-03 21:45:57
【问题描述】:

考虑这个 JSON 输入:

{
  "id":0,
  "Tags": [
    {"Key":"Name", "Value":"machine1"},
    {"Key":"Stage", "Value":"UAT"}
  ]
},
{
  "id":1,
  "Tags": [
    {"Key":"Stage", "Value":"UAT"}
  ]
},
{
  "id":2,
  "Tags": []
},
{
  "id":3
}

我寻求一种解决方案,在管道和选择之后将产生Value 字段的值,其中键NameName(none) 作为默认值。我得到的最接近的是:

jq -r 'if(.Tags == null or .Tags == []) then .Tags=[{"Key":"Name","Value":"(none)"}] else . end | "\(.id) \(.Tags[] | select(.Key == "Name")|.Value)" '

该解决方案适用于 id 0、2 和 3。当 Tags 数组存在但 包含 .Key == "Name" 时,选择会产生 null 并且没有值被退回。如果我再多考虑一下,我可能会偶然发现它,但是。理想情况下,我想做这样的事情(jq 伪代码):

Defend against null tags, then walk array looking for Name
'\(.Tags // [{}] | select(.Tags[].Key == "Name")?.Value // "(none)")

可能只是我确实还需要 1 个阶段,但我想探索其他聪明的可能性。

【问题讨论】:

  • 您的示例 JSON 输入似乎无效(我收到 jq: parse error: Expected value before ',' at line 7, column 2)。您的意思是写它时不使用逗号分隔对象吗?
  • 要解析逗号分隔的 JSON,并在单独的行上分隔逗号,请参阅 jq 常见问题解答(查找:def iterate(f): def r: f | (., r); r;

标签: jq


【解决方案1】:

这个jq 脚本应该可以解决问题:

{
  id,
  name: (first(.Tags[] | select(.Key == "Name").Value)? // "(none)")
}
| "\(.id) \(.name)"

它的工作方式类似于您的伪代码,但它不会主动防御 .Tags 数组不存在或为空。与它存在但不包含Name 条目的情况相比,没有特别的理由将其区别对待。该程序只是尝试访问Name 条目的.Value,如果由于任何原因根本不起作用,它将替换"(none)"

你可以把它放在一个文件中,也可以直接用

$ jq -r '{id, name: ...} | "\(.id) \(.name)"' input.json

【讨论】:

  • 啊,是的!将所有失败的 oppty 打包到一个受 ? 保护的表达式中,如果其中任何一个失败,则使用默认值。出色地使用first 来创建包?与只是一个 wrapper () 的 piar 相比,实际上应该只有一个 Key = Name 条目。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-10-05
  • 1970-01-01
  • 2021-12-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-29
相关资源
最近更新 更多