
다음 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