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

.[]에서 요소를 선택하면 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"
  }
]

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

관련 정보