Cómo fusionar 2 archivos json usando jq?

Estoy usando las herramientas jq (jq-json-processor) en el script de shell para analizar json.

Tengo 2 archivos json y quiero unirlos en un único archivo

Aquí el contenido de los archivos:

archivo1

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

archivo2

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

Resultado Esperado

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

Probé mucho combinaison pero el único resultado que obtengo es el siguiente, que no es el resultado esperado:

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

Usando este comando:

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

Desde 1.4 esto ahora es posible con el operador * . Cuando se le presenten dos objetos, los fusionará recursivamente. Por ejemplo,

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

Te atraparía:

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

Si también desea deshacerse de las otras claves (como su resultado esperado), una forma de hacerlo es esta:

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

O presumiblemente algo más eficiente (porque no fusiona ningún otro valor):

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

Use jq -s add :

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

Esto lee todos los textos JSON de stdin en una matriz ( jq -s hace) y luego los “reduce”.

( add se define como def add: reduce .[] as $x (null; . + $x); , que itera sobre los valores de la matriz de entrada / objeto y los agrega. Adición de objetos == fusión.)

Quién sabe si aún lo necesita, pero aquí está la solución.

Una vez que llegue a la opción --slurp , ¡es fácil!

 --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. 

Entonces el operador + hará lo que quieras:

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

(Nota: si desea fusionar objetos internos en lugar de sobrescribir los archivos de la izquierda con los archivos correctos, tendrá que hacerlo manualmente)

Aquí hay una versión que funciona recursivamente (usando * ) en un número arbitrario de objetos:

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

Primero, {“valor”: .value} se puede abreviar a solo {value}.

Segundo, la opción –argfile (disponible en jq 1.4 y jq 1.5) puede ser de interés ya que evita tener que usar la opción –slurp.

Al juntarlos, los dos objetos en los dos archivos se pueden combinar de la manera especificada de la siguiente manera:

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

La bandera ‘-n’ le dice a jq que no lea de stdin, ya que las entradas provienen de las opciones –argfile aquí.

    Intereting Posts