jq를 사용하여 2 개의 파일에서 2 개의 JSON 객체를 병합하는 방법은 무엇입니까?


123

내가 사용하고 JQ의 구문 분석 JSON에 쉘 스크립트 도구 (JQ-JSON 프로세서를).

2 개의 json 파일이 있으며 하나의 고유 한 파일로 병합 하고 싶습니다.

다음은 파일 내용입니다.

file1

{
    "value1": 200,
    "timestamp": 1382461861,
    "value": {
        "aaa": {
            "value1": "v1",
            "value2": "v2"
        },
        "bbb": {
            "value1": "v1",
            "value2": "v2"
        },
        "ccc": {
            "value1": "v1",
            "value2": "v2"
        }
    }
}

file2

{
    "status": 200,
    "timestamp": 1382461861,
    "value": {
        "aaa": {
            "value3": "v3",
            "value4": 4
        },
        "bbb": {
            "value3": "v3"
        },      
        "ddd": {
            "value3": "v3",
            "value4": 4
        }
    }
}

예상 결과

{
    "value": {
        "aaa": {
            "value1": "v1",
            "value2": "v2",
            "value3": "v3",
            "value4": 4
        },
        "bbb": {
            "value1": "v1",
            "value2": "v2",
            "value3": "v3"
        },
        "ccc": {
            "value1": "v1",
            "value2": "v2"
        },
        "ddd": {
            "value3": "v3",
            "value4": 4
        }
    }
}

나는 많은 조합을 시도했지만 내가 얻는 유일한 결과는 예상되는 결과가 아닌 다음과 같습니다.

{
  "ccc": {
    "value2": "v2",
    "value1": "v1"
  },
  "bbb": {
    "value2": "v2",
    "value1": "v1"
  },
  "aaa": {
    "value2": "v2",
    "value1": "v1"
  }
}
{
  "ddd": {
    "value4": 4,
    "value3": "v3"
  },
  "bbb": {
    "value3": "v3"
  },
  "aaa": {
    "value4": 4,
    "value3": "v3"
  }
}

이 명령 사용 :

jq -s '.[].value' file1 file2

1
jsontool을 사용해 보셨습니까? github.com/trentm/json
Nano Taboada

아직은 제가 살펴 볼게요. Thx
Janfy 2013-10-27

json사용하여 이를 수행하려면 :cat f1 f2 | json --deep-merge
xer0x 2014

json@ xer0x 는 어디서 / 어떻게 얻습니까?
Gus

@Gus 오, json도구 를 얻으려면 github.com/trentm/json으로
xer0x 2017

답변:


154

1.4부터 이것은 이제 *운영자 와 함께 가능합니다 . 두 개의 객체가 주어지면 재귀 적으로 병합합니다. 예를 들면

jq -s '.[0] * .[1]' file1 file2

중요 : -s (--slurp)파일을 동일한 배열에 넣는 플래그에 유의하십시오 .

당신을 얻을 것 :

{
  "value1": 200,
  "timestamp": 1382461861,
  "value": {
    "aaa": {
      "value1": "v1",
      "value2": "v2",
      "value3": "v3",
      "value4": 4
    },
    "bbb": {
      "value1": "v1",
      "value2": "v2",
      "value3": "v3"
    },
    "ccc": {
      "value1": "v1",
      "value2": "v2"
    },
    "ddd": {
      "value3": "v3",
      "value4": 4
    }
  },
  "status": 200
}

예상 결과와 같이 다른 키도 제거하려면 다음과 같이하십시오.

jq -s '.[0] * .[1] | {value: .value}' file1 file2

또는 아마도 다소 더 효율적일 것입니다 (다른 값을 병합하지 않기 때문에).

jq -s '.[0].value * .[1].value | {value: .}' file1 file2

2
참고 : -s플래그가 없으면 두 개체가 배열에 없기 때문에 플래그가 중요합니다.
John Morales

1
@SimoKinnunen 여기서 우리는 두 개의 json 파일을 병합합니다. 1 개의 json 변수와 다른 json 파일을 가질 수 있습니까? 시도했지만 작동하지 않는 것 같습니다!
Jayesh Dhandha

개별 파일이 키로 정렬 된 경우 결과 파일에서 순서를 유지할 수 있습니까?
레오

@SimoKinnunen이 명령을 사용하고 있습니다 : "jq -s 'add'config.json other / *. json"하지만 "cat config.json"을 수행하면 병합되지 않습니다. 출력을 파일에 다시 넣으려면 어떻게해야합니까?
Renato Bibiano

63

사용 jq -s add:

$ echo '{"a":"foo","b":"bar"} {"c":"baz","a":0}' | jq -s add
{
  "a": 0,
  "b": "bar",
  "c": "baz"
}

이것은 stdin의 모든 JSON 텍스트를 배열로 읽은 jq -s다음 (그렇게) "줄입니다".

( add로 정의 def add: reduce .[] as $x (null; . + $x);입력 배열의 / 개체 값로 반복. 개체 첨가 == 병합으로 추가한다.)


4
이 접근 방식으로 재귀 병합 (* 연산자)을 수행 할 수 있습니까?
Dave Foster

1
@DaveFoster 예, 다음과 같습니다 . jrib의 답변reduce .[] as $x ({}; . * $x) 도 참조하십시오 .
Chriki

이것은 Ansible과 jq를 사용하여 두 개의 json 파일을 병합하는 데 도움이되었습니다. 감사.
Felipe Alvarez

35

여전히 필요한지 누가 알지만 여기에 해결책이 있습니다.

--slurp옵션에 도달하면 쉽습니다!

--slurp/-s:
    Instead of running the filter for each JSON object in the input,
    read the entire input stream into a large array and run the filter just once.

그러면 +운영자가 원하는 작업을 수행합니다.

jq -s '.[0] + .[1]' config.json config-user.json

(참고 : 왼쪽 파일을 오른쪽 파일로 덮어 쓰는 대신 내부 개체를 병합하려면 수동으로 수행해야합니다.)


19

다음 *은 임의의 수의 객체에 대해 재귀 적으로 작동하는 버전입니다 (사용 ).

echo '{"A": {"a": 1}}' '{"A": {"b": 2}}' '{"B": 3}' | jq --slurp 'reduce .[] as $item ({}; . * $item)'
{
  "A": {
    "a": 1,
    "b": 2
  },
  "B": 3
}

2
좋은 대답입니다. 디렉토리에있는 모든 파일을 병합 할 때 잘 작동합니다 :jq -s 'reduce .[] as $item ({}; . * $item)' *.json
존 Ellmore

7

첫째, { "value": .value}는 {value}로 축약 될 수 있습니다.

둘째, --argfile 옵션 (jq 1.4 및 jq 1.5에서 사용 가능)은 --slurp 옵션을 사용할 필요가 없기 때문에 관심이있을 수 있습니다.

이들을 합치면 두 파일의 두 개체를 다음과 같이 지정된 방식으로 결합 할 수 있습니다.

$ jq -n --argfile o1 file1 --argfile o2 file2 '$o1 * $o2 | {value}'

'-n'플래그는 입력이 여기에있는 --argfile 옵션에서 나오기 때문에 jq에게 stdin에서 읽지 않도록 지시합니다.


2
JQ는 사용되지 않는 한 --argile대한--slurpfile
데이비드 Groomes

3

이것은 명령에 지정된 파일을 병합하는 데 사용할 수 있습니다.

jq -rs 'reduce .[] as $item ({}; . * $item)' file1.json file2.json file3.json ... file10.json

또는 이것은 여러 파일에 대해

jq -rs 'reduce .[] as $item ({}; . * $item)' ./*.json

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.