添加/修改 json 对象中的键/值

添加/修改 json 对象中的键/值

我问过类似的问题过去但我很难适应这个问题的解决方案。

我有以下 json 数组:

$ jq <<<"$json"
[
  {
    "id": "node1"
  },
  {
    "id": "node2"
  },
  {
    "id": "node3"
  }
]

我想向每个节点添加一个键/值或修改它(如果它已经存在)。我可以这样做:

$ jq '.[] | select(.id == "node2") += {status: "fail"}' <<<"$json"
{
  "id": "node1"
}
{
  "id": "node2",
  "status": "fail"
}
{
  "id": "node3"
}

但请注意,外部数组消失了,因此当我尝试在脚本中实现此解决方案时,它失败了。

#!/usr/bin/env bash

[[ $DEBUG == true ]] && set -x

nodes=(node1 node2 node3)
json='[{"id": "node1"},{"id": "node2"},{"id": "node3"}]'

for node in "${nodes[@]}"; do
    if [[ $node == node2 ]]; then
        status=fail
    else
        status=pass
    fi
    json=$(jq --arg status "$status" --arg node "$node" '.[] | select(.id == $node) += {status: $status}' <<<"$json")
done

错误:

$ ./script.sh
jq: error (at <stdin>:4): Cannot index string with string "id"
jq: error (at <stdin>:7): Cannot index string with string "id"
jq: error (at <stdin>:10): Cannot index string with string "id"

有没有办法可以修改这些 json 对象,同时保留整体结构?

答案1

.[]一旦您从with中选择了一个元素select(),这就是您剩下的唯一数据以及最后将输出的内容。

相反,使用map()对顶级数组的每个元素应用(可能的)修改:

$ jq --arg id node2 --arg status fail 'map(select(.id == $id) += { status: $status } )' file
[
  {
    "id": "node1"
  },
  {
    "id": "node2",
    "status": "fail"
  },
  {
    "id": "node3"
  }
]

或者可能更整洁,用更少的大括号,

$ jq --arg id node2 --arg status fail 'map(select(.id == $id).status = $status)' file
[
  {
    "id": "node1"
  },
  {
    "id": "node2",
    "status": "fail"
  },
  {
    "id": "node3"
  }
]

复制 shell 循环jq以避免多次调用jq

$ jq --arg failnode node2 'map(.status = if .id == $failnode then "fail" else "pass" end)' file
[
  {
    "id": "node1",
    "status": "pass"
  },
  {
    "id": "node2",
    "status": "fail"
  },
  {
    "id": "node3",
    "status": "pass"
  }
]

--args或者,使多个节点失败,并在命令行上列出每个失败的节点(请注意最后的非正统但必要的放置):

$ jq 'map(.status = if (.id|IN($ARGS.positional[])) then "fail" else "pass" end)' file --args node1 node2
[
  {
    "id": "node1",
    "status": "fail"
  },
  {
    "id": "node2",
    "status": "fail"
  },
  {
    "id": "node3",
    "status": "pass"
  }
]

相关内容