with_entries 메소드를 사용하여 jq로 키 이름을 재귀적으로 변경할 수 있습니까?

with_entries 메소드를 사용하여 jq로 키 이름을 재귀적으로 변경할 수 있습니까?

다음 JSON 파일이 있다고 가정해 보겠습니다.

[
  {
    "name1": "fruits",
    "name2": "cars",
    "name3": "houses"
  }
]

jq다음과 같이 값의 이름을 바꾸는 데 사용할 수 있다는 것을 알고 있습니다 .

jq '[.[] | .["newname1"] = .name1 | del(.name1)]' file

이것은 잘 작동하며 더 복잡한 JSON 구조에서도 변경할 수 있습니다. 그러나 이는 변경하려는 키에 대한 매우 명시적인 선언입니다. 동일한 작업을 수행하는 다른 방법은 다음 명령을 사용하는 것입니다.

jq 'map(with_entries(if .key == "name1" then .key = "newname1" else . end))' file 

객체 배열인 JSON 내부에서 특정 이름을 가진 모든 키를 확인하고 변경하는 방법입니다. key이 경우에는 이름을 명시적으로 선언할 필요가 없습니다 . 그러나 이는 객체 배열에서만 작동합니다. 재귀적인 방식으로 json 내부의 모든 키를 변경하는 방법을 찾고 싶습니다. 다음과 같은 JSON이 있다고 가정해 보겠습니다.

{
  "name1": "one",
  "type": "FeatureCollection",
  "features": [
    {
      "name1": "one",
      "valueA": "0",
      "valueB": "0",
      "keyB": "2",
      "keyC": "3"
    },
    {
      "name1": "two",
      "valueA": "11",
      "valueB": "21",
      "keyB": "15",
      "keyC": "20"
    }
  ]
}

내 마지막 jq명령은 이 JSON에서 작동하지 않습니다. name1를 사용하여 모든 키를 재귀적으로 변경하는 방법이 있습니까 jq? 아마도 recurse(.[]?;true)이 명령과 함께 사용하는 방법을 찾을 수 있을까요 ? 가능합니까?

답변1

jq 'walk(if type == "object" then with_entries( if .key == "name1" then .key = "newname1" else . end ) else . end)' file

jq이는 매뉴얼(기능을 설명하는 섹션 walk()) 에서 거의 직접적으로 나온 내용입니다 . 이 walk()함수는 "재귀 map()"처럼 작동하며 우리가 주의해야 할 유일한 것은 현재 다루고 있는 엔터티의 유형을 확인하는 것입니다.

를 사용하면 walk()첫 번째 접근 방식을 적용할 수도 있습니다.

jq 'walk(if type == "object" and has("name1") then ( .newname1 = .name1 | del(.name1) ) else . end)' file

그러나 이렇게 하면 키 가 발견된 위치에서 newname1교체되지 않고(중요한 경우) 각 객체의 마지막에 키가 배치됩니다 .name1

1.6 의 또 다른 접근 방식 jq은 재귀 괜찮은 연산자를 사용하여 ..찾고 있는 키가 있는 항목을 선택한 다음 해당 개체를 업데이트하는 것입니다.

jq '(.. | select(has("name1")?)) |= with_entries(if .key == "name1" then .key = "newname1" else . end)' file

관련 정보