{}和select之间的交互

时间:2014-07-27 04:18:10

标签: jq

这是我的测试数据:

[
  {
    "id": "id-1",
    "tags": {
      "key": "name",
      "value": "name-1"
    }
  },
  {
    "id": "id-2"
  }
]

我试图简化输出,以显示'名称'字段,如果存在,并始终显示ID。例如,这个脚本几乎可以工作:

~ $ cat testdata | jq '.[] | {id, name: .tags.value}'

{
  "id": "id-1",
  "name": "name-1"
}
{
  "id": "id-2",
  "name": null
}

当我尝试添加针对.keys不存在的警示并过滤“'键的部分'我关心,发生了什么:

~ $ cat testdata | jq '.[] | {id, name: (select(.tags.key == "name") | .tags.value)}'

{
  "id": "id-1",
  "name": "name-1"
}

我认为{}以某种方式结束了零长度数组,而不是' null'。我该怎么用而不是|?我误解了什么?

4 个答案:

答案 0 :(得分:0)

我最终使用[POSSIBLY_MATCHED_EXPRESSION][0]来解决问题,在这种情况下:

 cat testdata | jq '.[] | {id, name: ([select(.tags.key == "name") | .tags.value][0])}'

答案 1 :(得分:0)

如果我理解正确,如果您只想包含名称,请执行以下操作:

map({id} + with_entries(select(.key == "tags") | .value))

否则,如果您不介意null名称:

map({id, name: with_entries(select(.key == "tags") | .value) | .name})

如果您有其他"标签,那么这是一个更通用的解决方案。所以它不是硬编码只接受name值。

这假设任何对象值实际上是键/值对。

map(with_entries(if .value | type == "object" then .value else . end))

或者tags是唯一的动态属性:

map(with_entries(if .key == "tags" then .value else . end))

答案 2 :(得分:0)

如果目标是产生:

{"id":"id-1","name":"name-1"}
{"id":"id-2"}

那么以下三个表达式基本上是等价的解决方案:

.[] | if .tags.key == "name" then {id, name: .tags.value} else {id} end

.[] | {id} + (if .tags.key == "name" then {name: .tags.value} else {} end)

.[] | (select(.tags.key  == "name") | {id, name: .tags.value}) // {id}

答案 3 :(得分:0)

你可以添加

| if .name == null then del(.name) else . end

到过滤器的末尾,以便在其值为null时删除.name键。 使用您的测试数据,以下

  .[]
| {id, name:.tags.value }
| if .name == null then del(.name) else . end

产生

{
  "id": "id-1",
  "name": "name-1"
}
{
  "id": "id-2"
}